treewide: replace error comparisons and assertions with errors.Is

Change-Id: Id2424eb155f2c6842c72c5fafd124d428ef901f2
Reviewed-on: https://review.monogon.dev/c/monogon/+/2994
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/metropolis/cli/metroctl/cmd_certs.go b/metropolis/cli/metroctl/cmd_certs.go
index e0bfd41..075a0d0 100644
--- a/metropolis/cli/metroctl/cmd_certs.go
+++ b/metropolis/cli/metroctl/cmd_certs.go
@@ -3,6 +3,7 @@
 import (
 	"crypto/x509"
 	"encoding/pem"
+	"errors"
 	"log"
 	"os"
 
@@ -28,7 +29,7 @@
 	Example: "metroctl cert export",
 	Run: func(cmd *cobra.Command, args []string) {
 		ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
-		if err == core.NoCredentialsError {
+		if errors.Is(err, core.NoCredentialsError) {
 			log.Fatalf("You have to take ownership of the cluster first: %v", err)
 		}
 
diff --git a/metropolis/cli/metroctl/cmd_k8scredplugin.go b/metropolis/cli/metroctl/cmd_k8scredplugin.go
index 9b3226e..adc3fe8 100644
--- a/metropolis/cli/metroctl/cmd_k8scredplugin.go
+++ b/metropolis/cli/metroctl/cmd_k8scredplugin.go
@@ -4,6 +4,7 @@
 	"crypto/x509"
 	"encoding/json"
 	"encoding/pem"
+	"errors"
 	"log"
 	"os"
 
@@ -27,7 +28,7 @@
 
 func doK8sCredPlugin(cmd *cobra.Command, args []string) {
 	cert, key, err := core.GetOwnerCredentials(flags.configPath)
-	if err == core.NoCredentialsError {
+	if errors.Is(err, core.NoCredentialsError) {
 		log.Fatal("No credentials found on your machine")
 	}
 	if err != nil {
diff --git a/metropolis/cli/metroctl/cmd_takeownership.go b/metropolis/cli/metroctl/cmd_takeownership.go
index dd4bfb4..adad3cf 100644
--- a/metropolis/cli/metroctl/cmd_takeownership.go
+++ b/metropolis/cli/metroctl/cmd_takeownership.go
@@ -2,6 +2,7 @@
 
 import (
 	"context"
+	"errors"
 	"log"
 	"os"
 	"os/exec"
@@ -46,7 +47,7 @@
 	// Retrieve the cluster owner's private key, and use it to construct
 	// ephemeral credentials. Then, dial the cluster.
 	opk, err := core.GetOwnerKey(flags.configPath)
-	if err == core.NoCredentialsError {
+	if errors.Is(err, core.NoCredentialsError) {
 		log.Fatalf("Owner key does not exist. takeownership needs to be executed on the same system that has previously installed the cluster using metroctl install.")
 	}
 	if err != nil {
diff --git a/metropolis/cli/metroctl/core/ca_tofu.go b/metropolis/cli/metroctl/core/ca_tofu.go
index fc30c6c..9df9957 100644
--- a/metropolis/cli/metroctl/core/ca_tofu.go
+++ b/metropolis/cli/metroctl/core/ca_tofu.go
@@ -114,7 +114,7 @@
 	if err == nil {
 		return ca, nil
 	}
-	if err != NoCACertificateError {
+	if !errors.Is(err, NoCACertificateError) {
 		return nil, err
 	}
 
diff --git a/metropolis/cli/metroctl/core/config.go b/metropolis/cli/metroctl/core/config.go
index 639bfc3..f3ca8b3 100644
--- a/metropolis/cli/metroctl/core/config.go
+++ b/metropolis/cli/metroctl/core/config.go
@@ -48,10 +48,10 @@
 // directory path, generating and saving it first if it doesn't exist.
 func GetOrMakeOwnerKey(path string) (ed25519.PrivateKey, error) {
 	existing, err := GetOwnerKey(path)
-	switch err {
-	case nil:
+	switch {
+	case err == nil:
 		return existing, nil
-	case NoCredentialsError:
+	case errors.Is(err, NoCredentialsError):
 	default:
 		return nil, err
 	}
diff --git a/metropolis/cli/metroctl/rpc.go b/metropolis/cli/metroctl/rpc.go
index 164e2ee..06008e3 100644
--- a/metropolis/cli/metroctl/rpc.go
+++ b/metropolis/cli/metroctl/rpc.go
@@ -4,6 +4,7 @@
 	"context"
 	"crypto/tls"
 	"crypto/x509"
+	"errors"
 	"log"
 
 	"google.golang.org/grpc"
@@ -17,7 +18,7 @@
 	// Collect credentials, validate command parameters, and try dialing the
 	// cluster.
 	ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
-	if err == core.NoCredentialsError {
+	if errors.Is(err, core.NoCredentialsError) {
 		log.Fatalf("You have to take ownership of the cluster first: %v", err)
 	}
 	if len(flags.clusterEndpoints) == 0 {
@@ -51,7 +52,7 @@
 	// Collect credentials, validate command parameters, and try dialing the
 	// cluster.
 	ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
-	if err == core.NoCredentialsError {
+	if errors.Is(err, core.NoCredentialsError) {
 		log.Fatalf("You have to take ownership of the cluster first: %v", err)
 	}
 	cc, err := core.DialNode(ctx, opkey, ocert, cacert, flags.proxyAddr, id, address)
diff --git a/metropolis/node/core/curator/impl_leader_cluster_networking.go b/metropolis/node/core/curator/impl_leader_cluster_networking.go
index f4f6edc..4bd729d 100644
--- a/metropolis/node/core/curator/impl_leader_cluster_networking.go
+++ b/metropolis/node/core/curator/impl_leader_cluster_networking.go
@@ -2,6 +2,7 @@
 
 import (
 	"context"
+	"errors"
 	"net/netip"
 
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
@@ -32,7 +33,7 @@
 	defer w.Close()
 	for {
 		nodeKV, err := w.Get(ctx, event.BacklogOnly[*nodeAtID]())
-		if err == event.BacklogDone {
+		if errors.Is(err, event.BacklogDone) {
 			break
 		}
 		if err != nil {
diff --git a/metropolis/node/core/curator/impl_leader_curator.go b/metropolis/node/core/curator/impl_leader_curator.go
index 9cbbbe6..d45fc79 100644
--- a/metropolis/node/core/curator/impl_leader_curator.go
+++ b/metropolis/node/core/curator/impl_leader_curator.go
@@ -4,6 +4,7 @@
 	"context"
 	"crypto/ed25519"
 	"crypto/subtle"
+	"errors"
 	"fmt"
 	"io"
 	"net"
@@ -108,7 +109,7 @@
 	nodes := make(map[string]*Node)
 	for {
 		nodeKV, err := w.Get(ctx, event.BacklogOnly[*nodeAtID]())
-		if err == event.BacklogDone {
+		if errors.Is(err, event.BacklogDone) {
 			break
 		}
 		if err != nil {
@@ -359,7 +360,7 @@
 		rpc.Trace(ctx).Printf("node %s already exists in cluster, failing", id)
 		return nil, status.Errorf(codes.FailedPrecondition, "node already exists in cluster, state %s", node.state.String())
 	}
-	if err != errNodeNotFound {
+	if !errors.Is(err, errNodeNotFound) {
 		return nil, err
 	}
 
diff --git a/metropolis/node/core/curator/impl_leader_management.go b/metropolis/node/core/curator/impl_leader_management.go
index 9d5b4cd..2fe5e6c 100644
--- a/metropolis/node/core/curator/impl_leader_management.go
+++ b/metropolis/node/core/curator/impl_leader_management.go
@@ -4,6 +4,7 @@
 	"bytes"
 	"context"
 	"crypto/ed25519"
+	"errors"
 	"sort"
 	"time"
 
@@ -319,7 +320,7 @@
 
 	// Find the node matching the requested public key.
 	node, err := nodeLoad(ctx, l.leadership, id)
-	if err == errNodeNotFound {
+	if errors.Is(err, errNodeNotFound) {
 		return nil, status.Errorf(codes.NotFound, "node %s not found", id)
 	}
 	if err != nil {
@@ -413,7 +414,7 @@
 
 	// Find the node matching the requested public key.
 	node, err := nodeLoad(ctx, l.leadership, id)
-	if err == errNodeNotFound {
+	if errors.Is(err, errNodeNotFound) {
 		return nil, status.Errorf(codes.NotFound, "node %s not found", id)
 	}
 	if err != nil {
diff --git a/metropolis/node/core/mgmt/svc_logs.go b/metropolis/node/core/mgmt/svc_logs.go
index 9d27d63..b24e485 100644
--- a/metropolis/node/core/mgmt/svc_logs.go
+++ b/metropolis/node/core/mgmt/svc_logs.go
@@ -1,6 +1,7 @@
 package mgmt
 
 import (
+	"errors"
 	"strings"
 
 	"google.golang.org/grpc/codes"
@@ -63,9 +64,9 @@
 	}
 	dn := logtree.DN(req.Dn)
 	_, err := dn.Path()
-	switch err {
-	case nil:
-	case logtree.ErrInvalidDN:
+	switch {
+	case err == nil:
+	case errors.Is(err, logtree.ErrInvalidDN):
 		return status.Errorf(codes.InvalidArgument, "invalid DN")
 	default:
 		return status.Errorf(codes.Unavailable, "could not parse DN: %v", err)
@@ -116,9 +117,9 @@
 	}
 
 	reader, err := s.LogTree.Read(logtree.DN(req.Dn), options...)
-	switch err {
-	case nil:
-	case logtree.ErrRawAndLeveled:
+	switch {
+	case err == nil:
+	case errors.Is(err, logtree.ErrRawAndLeveled):
 		return status.Errorf(codes.InvalidArgument, "requested only raw and only leveled logs simultaneously")
 	default:
 		return status.Errorf(codes.Unavailable, "could not retrieve logs: %v", err)
diff --git a/metropolis/node/kubernetes/csi.go b/metropolis/node/kubernetes/csi.go
index f150a13..c0d81bb 100644
--- a/metropolis/node/kubernetes/csi.go
+++ b/metropolis/node/kubernetes/csi.go
@@ -18,6 +18,7 @@
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"net"
 	"os"
@@ -107,7 +108,7 @@
 	case *csi.VolumeCapability_Mount:
 		err := unix.Mount(volumePath, req.TargetPath, "", unix.MS_BIND, "")
 		switch {
-		case err == unix.ENOENT:
+		case errors.Is(err, unix.ENOENT):
 			return nil, status.Error(codes.NotFound, "volume not found")
 		case err != nil:
 			return nil, status.Errorf(codes.Unavailable, "failed to bind-mount volume: %v", err)
diff --git a/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go b/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
index b9b4fb4..902803b 100644
--- a/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
+++ b/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
@@ -26,6 +26,7 @@
 import (
 	"bytes"
 	"context"
+	"errors"
 	"fmt"
 	"net"
 	"os"
@@ -158,7 +159,7 @@
 	kvmDevNode, err := deviceNumberFromString(string(kvmDevRaw))
 
 	err = unix.Mknod("/dev/kvm", 0660, int(kvmDevNode))
-	if err != nil && err != unix.EEXIST {
+	if err != nil && errors.Is(err, unix.EEXIST) {
 		return fmt.Errorf("failed to create KVM device node: %v", err)
 	}
 
diff --git a/metropolis/pkg/blockdev/blockdev_linux.go b/metropolis/pkg/blockdev/blockdev_linux.go
index 6d87c87..b5ef106 100644
--- a/metropolis/pkg/blockdev/blockdev_linux.go
+++ b/metropolis/pkg/blockdev/blockdev_linux.go
@@ -72,7 +72,7 @@
 		// Attempts to leverage discard guarantees to provide extremely quick
 		// metadata-only zeroing.
 		err = unix.Fallocate(int(fd), unix.FALLOC_FL_PUNCH_HOLE|unix.FALLOC_FL_KEEP_SIZE, startByte, endByte-startByte)
-		if err == unix.EOPNOTSUPP {
+		if errors.Is(err, unix.EOPNOTSUPP) {
 			// Tries Write Same and friends and then just falls back to writing
 			// zeroes.
 			_, _, err = unix.Syscall(unix.SYS_IOCTL, fd, unix.BLKZEROOUT, uintptr(unsafe.Pointer(&args[0])))
diff --git a/metropolis/pkg/event/etcd/etcd_test.go b/metropolis/pkg/event/etcd/etcd_test.go
index 6173732..d4eb04f 100644
--- a/metropolis/pkg/event/etcd/etcd_test.go
+++ b/metropolis/pkg/event/etcd/etcd_test.go
@@ -131,7 +131,7 @@
 		if err == nil {
 			return
 		}
-		if err == ctxT.Err() {
+		if errors.Is(err, ctxT.Err()) {
 			log.Printf("Retrying after %v", err)
 			continue
 		}
@@ -776,7 +776,7 @@
 	// As expected, next call to Get with BacklogOnly fails - there truly is no new
 	// updates to emit.
 	_, err = watcher.Get(ctx, event.BacklogOnly[StringAt]())
-	if want, got := event.BacklogDone, err; want != got {
+	if want, got := event.BacklogDone, err; !errors.Is(got, want) {
 		t.Fatalf("Second Get: wanted %v, got %v", want, got)
 	}
 
@@ -784,7 +784,7 @@
 	// BacklogOnly will still return BacklogDone.
 	tc.put(t, k, "second")
 	_, err = watcher.Get(ctx, event.BacklogOnly[StringAt]())
-	if want, got := event.BacklogDone, err; want != got {
+	if want, got := event.BacklogDone, err; !errors.Is(got, want) {
 		t.Fatalf("Third Get: wanted %v, got %v", want, got)
 	}
 
@@ -840,7 +840,7 @@
 	nUpdates := 1
 	for {
 		g, err := w.Get(ctx, event.BacklogOnly[StringAt]())
-		if err == event.BacklogDone {
+		if errors.Is(err, event.BacklogDone) {
 			break
 		}
 		if err != nil {
diff --git a/metropolis/pkg/event/memory/memory_test.go b/metropolis/pkg/event/memory/memory_test.go
index 98a1501..80ac575 100644
--- a/metropolis/pkg/event/memory/memory_test.go
+++ b/metropolis/pkg/event/memory/memory_test.go
@@ -18,6 +18,7 @@
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"sync"
 	"sync/atomic"
@@ -294,7 +295,7 @@
 
 	// Cancel the context, and expect that context error to propagate to the .Get().
 	ctxC()
-	if want, got := ctx.Err(), <-errs; want != got {
+	if want, got := ctx.Err(), <-errs; !errors.Is(got, want) {
 		t.Fatalf("Get should've returned %v, got %v", want, got)
 	}
 
@@ -308,7 +309,7 @@
 
 	// Unblock the .Get now.
 	p.Set(1)
-	if want, got := error(nil), <-errs; want != got {
+	if want, got := error(nil), <-errs; !errors.Is(got, want) {
 		t.Fatalf("Get should've returned %v, got %v", want, got)
 	}
 }
diff --git a/metropolis/pkg/fsquota/fsquota.go b/metropolis/pkg/fsquota/fsquota.go
index 1cdcd54..af87d9f 100644
--- a/metropolis/pkg/fsquota/fsquota.go
+++ b/metropolis/pkg/fsquota/fsquota.go
@@ -22,6 +22,7 @@
 package fsquota
 
 import (
+	"errors"
 	"fmt"
 	"math"
 	"os"
@@ -66,7 +67,7 @@
 		// infrequent calls this should not be an immediate issue.
 		for {
 			quota, err := quotactl.GetNextQuota(dir, quotactl.QuotaTypeProject, lastID)
-			if err == unix.ENOENT || err == unix.ESRCH {
+			if errors.Is(err, unix.ENOENT) || errors.Is(err, unix.ESRCH) {
 				// We have enumerated all quotas, nothing exists here
 				break
 			} else if err != nil {
diff --git a/metropolis/pkg/kmod/manager.go b/metropolis/pkg/kmod/manager.go
index 1630a7f..3b3f875 100644
--- a/metropolis/pkg/kmod/manager.go
+++ b/metropolis/pkg/kmod/manager.go
@@ -2,6 +2,7 @@
 
 import (
 	"bufio"
+	"errors"
 	"fmt"
 	"os"
 	"path/filepath"
@@ -150,7 +151,7 @@
 	}
 	defer module.Close()
 	err = LoadModule(module, "", 0)
-	if err != nil && err != unix.EEXIST {
+	if err != nil && errors.Is(err, unix.EEXIST) {
 		return fmt.Errorf("error loading kernel module %v: %w", modMeta.Name, err)
 	}
 	s.loadedModules[modIdx] = true
diff --git a/metropolis/pkg/scsi/inquiry.go b/metropolis/pkg/scsi/inquiry.go
index 45c1603..bce2c9a 100644
--- a/metropolis/pkg/scsi/inquiry.go
+++ b/metropolis/pkg/scsi/inquiry.go
@@ -3,6 +3,7 @@
 import (
 	"bytes"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"io"
 	"math"
@@ -27,7 +28,7 @@
 	rawReader := io.LimitReader(bytes.NewReader(data), resLen)
 	var raw inquiryDataRaw
 	if err := binary.Read(rawReader, binary.BigEndian, &raw); err != nil {
-		if err == io.ErrUnexpectedEOF {
+		if errors.Is(err, io.ErrUnexpectedEOF) {
 			return nil, fmt.Errorf("response to INQUIRY is smaller than %d bytes, very old or broken device", binary.Size(raw))
 		}
 		panic(err) // Read from memory, shouldn't be possible to hit
@@ -67,14 +68,14 @@
 	}
 	var padding [2]byte
 	if _, err := io.ReadFull(rawReader, padding[:]); err != nil {
-		if err == io.ErrUnexpectedEOF {
+		if errors.Is(err, io.ErrUnexpectedEOF) {
 			return &res, nil
 		}
 	}
 	for i := 0; i < 8; i++ {
 		var versionDesc uint16
 		if err := binary.Read(rawReader, binary.BigEndian, &versionDesc); err != nil {
-			if err == io.EOF || err == io.ErrUnexpectedEOF {
+			if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
 				return &res, nil
 			}
 		}
diff --git a/metropolis/pkg/socksproxy/socksproxy.go b/metropolis/pkg/socksproxy/socksproxy.go
index dfd32c4..808ae1f 100644
--- a/metropolis/pkg/socksproxy/socksproxy.go
+++ b/metropolis/pkg/socksproxy/socksproxy.go
@@ -17,6 +17,7 @@
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"io"
 	"log"
@@ -173,14 +174,14 @@
 
 	// Read request from the client and translate problems into early error replies.
 	req, err := readRequest(con)
-	switch err {
-	case errNotConnect:
+	switch {
+	case errors.Is(err, errNotConnect):
 		writeReply(con, ReplyCommandNotSupported, net.IPv4(0, 0, 0, 0), 0)
 		return
-	case errUnsupportedAddressType:
+	case errors.Is(err, errUnsupportedAddressType):
 		writeReply(con, ReplyAddressTypeNotSupported, net.IPv4(0, 0, 0, 0), 0)
 		return
-	case nil:
+	case err == nil:
 	default:
 		writeReply(con, ReplyGeneralFailure, net.IPv4(0, 0, 0, 0), 0)
 		return
diff --git a/metropolis/pkg/tpm/eventlog/secureboot.go b/metropolis/pkg/tpm/eventlog/secureboot.go
index d2aa721..090be5c 100644
--- a/metropolis/pkg/tpm/eventlog/secureboot.go
+++ b/metropolis/pkg/tpm/eventlog/secureboot.go
@@ -163,7 +163,7 @@
 			a, err := internal.ParseUEFIVariableAuthority(bytes.NewReader(e.Data))
 			if err != nil {
 				// Workaround for: https://github.com/google/go-attestation/issues/157
-				if err == internal.ErrSigMissingGUID {
+				if errors.Is(err, internal.ErrSigMissingGUID) {
 					// Versions of shim which do not carry
 					// https://github.com/rhboot/shim/commit/8a27a4809a6a2b40fb6a4049071bf96d6ad71b50
 					// have an erroneous additional byte in the event, which breaks digest
diff --git a/metropolis/pkg/verity/encoder.go b/metropolis/pkg/verity/encoder.go
index a1c0ca1..871cec0 100644
--- a/metropolis/pkg/verity/encoder.go
+++ b/metropolis/pkg/verity/encoder.go
@@ -45,6 +45,7 @@
 	"crypto/sha256"
 	"encoding/binary"
 	"encoding/hex"
+	"errors"
 	"fmt"
 	"io"
 	"strconv"
@@ -177,9 +178,9 @@
 			dcnt++
 		}
 		// Handle the read errors.
-		switch err {
-		case nil:
-		case io.ErrUnexpectedEOF, io.EOF:
+		switch {
+		case err == nil:
+		case errors.Is(err, io.ErrUnexpectedEOF), errors.Is(err, io.EOF):
 			// io.ReadFull returns io.ErrUnexpectedEOF after a partial read,
 			// and io.EOF if no bytes were read. In both cases it's possible
 			// to end up with a partially filled hash block.
diff --git a/metropolis/test/e2e/k8s_cts/main.go b/metropolis/test/e2e/k8s_cts/main.go
index 4b86b64..6383cb8 100644
--- a/metropolis/test/e2e/k8s_cts/main.go
+++ b/metropolis/test/e2e/k8s_cts/main.go
@@ -21,6 +21,7 @@
 
 import (
 	"context"
+	"errors"
 	"io"
 	"log"
 	"os"
@@ -159,7 +160,7 @@
 					log.Printf("Log pump error: %v", err)
 				}
 				logs.Close()
-			} else if err == ctx.Err() {
+			} else if errors.Is(err, ctx.Err()) {
 				return // Exit if the context has been cancelled
 			} else {
 				log.Printf("Pod logs not ready yet: %v", err)
@@ -170,7 +171,7 @@
 	for {
 		time.Sleep(1 * time.Second)
 		pod, err := clientSet.CoreV1().Pods("default").Get(ctx, podName, metav1.GetOptions{})
-		if err != nil && err == ctx.Err() {
+		if err != nil && errors.Is(err, ctx.Err()) {
 			return // Exit if the context has been cancelled
 		} else if err != nil {
 			log.Printf("Failed to get CTS pod: %v", err)
diff --git a/metropolis/test/util/runners.go b/metropolis/test/util/runners.go
index 99de4f1..a34c070 100644
--- a/metropolis/test/util/runners.go
+++ b/metropolis/test/util/runners.go
@@ -30,7 +30,7 @@
 				launch.Log("Test: %s: okay after %.1f seconds", name, time.Since(start).Seconds())
 				return
 			}
-			if err == ctx.Err() {
+			if errors.Is(err, ctx.Err()) {
 				t.Fatal(lastErr)
 			}
 			if errors.Is(err, &PermanentError{}) {