treewide: add missing error handling

Change-Id: I55ccf3ff490b58f6af93e665c668428acddc8d65
Reviewed-on: https://review.monogon.dev/c/monogon/+/3019
Vouch-Run-CI: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/build/bazel_cc_fix/main.go b/build/bazel_cc_fix/main.go
index ffd5edb..b115e50 100644
--- a/build/bazel_cc_fix/main.go
+++ b/build/bazel_cc_fix/main.go
@@ -328,6 +328,9 @@
 		log.Fatalf("failed to read compilation db: %v", err)
 	}
 	specRaw, err := os.ReadFile(*specPath)
+	if err != nil {
+		log.Fatalf("failed to read spec file: %v", err)
+	}
 	var spec ccfixspec.CCFixSpec
 	if err := prototext.Unmarshal(specRaw, &spec); err != nil {
 		log.Fatalf("failed to load spec: %v", err)
diff --git a/cloud/agent/e2e/main_test.go b/cloud/agent/e2e/main_test.go
index 02600fb..3a27803 100644
--- a/cloud/agent/e2e/main_test.go
+++ b/cloud/agent/e2e/main_test.go
@@ -122,6 +122,9 @@
 		BasicConstraintsValid: true,
 	}
 	serverCert, err := x509.CreateCertificate(rand.Reader, &serverCertTmpl, caCert, serverPubKey, caPrivKey)
+	if err != nil {
+		t.Fatal(err)
+	}
 
 	s := grpc.NewServer(grpc.Creds(credentials.NewServerTLSFromCert(&tls.Certificate{
 		Certificate: [][]byte{serverCert},
@@ -147,10 +150,14 @@
 	if err != nil {
 		t.Fatal(err)
 	}
+
 	blobListenAddr := blobLis.Addr().(*net.TCPAddr)
 	go http.Serve(blobLis, m)
 
 	_, privateKey, err := ed25519.GenerateKey(rand.Reader)
+	if err != nil {
+		t.Fatal(err)
+	}
 
 	init := apb.AgentInit{
 		TakeoverInit: &apb.TakeoverInit{
diff --git a/cloud/agent/takeover/takeover.go b/cloud/agent/takeover/takeover.go
index a62dc8c..094c688 100644
--- a/cloud/agent/takeover/takeover.go
+++ b/cloud/agent/takeover/takeover.go
@@ -165,6 +165,9 @@
 		agentParams = append(agentParams, bootparam.Param{Param: "console", Value: "ttyS0,115200"})
 	}
 	agentCmdline, err := bootparam.Marshal(agentParams, "")
+	if err != nil {
+		return nil, fmt.Errorf("failed to marshal agent params: %w", err)
+	}
 	// Stage agent payload into kernel memory
 	if err := kexec.FileLoad(kernelFile, initramfsFile, agentCmdline); err != nil {
 		return nil, fmt.Errorf("failed to load kexec payload: %w", err)
diff --git a/cloud/bmaas/bmdb/migrations_test.go b/cloud/bmaas/bmdb/migrations_test.go
index 65eef7f..1a70655 100644
--- a/cloud/bmaas/bmdb/migrations_test.go
+++ b/cloud/bmaas/bmdb/migrations_test.go
@@ -135,6 +135,9 @@
 	rows, err := conn.db.Query(`
 		SELECT machine_id, process, until, cause FROM work_backoff
 	`)
+	if err != nil {
+		t.Fatalf("Could not fetch old-style backoff data: %v", err)
+	}
 	for rows.Next() {
 		var mid, process, until, cause string
 		if err := rows.Scan(&mid, &process, &until, &cause); err != nil {
diff --git a/cloud/shepherd/provider/equinix/updater_test.go b/cloud/shepherd/provider/equinix/updater_test.go
index 9b23295..e400690 100644
--- a/cloud/shepherd/provider/equinix/updater_test.go
+++ b/cloud/shepherd/provider/equinix/updater_test.go
@@ -102,6 +102,9 @@
 			AgentPublicKey: []byte("fakefakefakefake"),
 		})
 	})
+	if err != nil {
+		t.Fatalf("failed to execute bmdb transaction: %v", err)
+	}
 
 	deadline := time.Now().Add(time.Second * 10)
 	for {
diff --git a/metropolis/installer/main.go b/metropolis/installer/main.go
index 6313548..a35a734 100644
--- a/metropolis/installer/main.go
+++ b/metropolis/installer/main.go
@@ -89,6 +89,9 @@
 	// Use the partition's name to find and return the name of its parent
 	// device. It will be excluded from the list of suitable target devices.
 	srcDev, err := sysfs.ParentBlockDevice(espDev)
+	if err != nil{
+		return nil, fmt.Errorf("failed to fetch parent device: %w", err)
+	}
 	// Build the exclusion list containing forbidden handle prefixes.
 	exclude := []string{"dm-", "zram", "ram", "loop", srcDev}
 
diff --git a/metropolis/installer/test/main.go b/metropolis/installer/test/main.go
index 3c2460a..b2fb8dc 100644
--- a/metropolis/installer/test/main.go
+++ b/metropolis/installer/test/main.go
@@ -273,6 +273,9 @@
 	}
 	// Verify that GPT exists.
 	ti, err := storage.GetPartitionTable()
+	if err != nil {
+		t.Fatalf("Couldn't read the installer image partition table: %s", err)
+	}
 	if ti.Type() != "gpt" {
 		t.Error("Couldn't verify that the resulting node image contains a GPT.")
 	}
diff --git a/metropolis/node/build/fwprune/main.go b/metropolis/node/build/fwprune/main.go
index dfabcde..4f26fa0 100644
--- a/metropolis/node/build/fwprune/main.go
+++ b/metropolis/node/build/fwprune/main.go
@@ -209,6 +209,9 @@
 	// Format output in a both human- and machine-readable form
 	marshalOpts := prototext.MarshalOptions{Multiline: true, Indent: "  "}
 	fsspecRaw, err := marshalOpts.Marshal(&fsspec.FSSpec{File: files, SymbolicLink: symlinks})
+	if err != nil {
+		log.Fatalf("failed to marshal fsspec: %v", err)
+	}
 	if err := os.WriteFile(*outFSSpecPath, fsspecRaw, 0644); err != nil {
 		log.Fatalf("failed writing output: %v", err)
 	}
diff --git a/metropolis/node/core/curator/state_node.go b/metropolis/node/core/curator/state_node.go
index d580e87..bd11f6a 100644
--- a/metropolis/node/core/curator/state_node.go
+++ b/metropolis/node/core/curator/state_node.go
@@ -446,7 +446,11 @@
 		return status.Errorf(codes.InvalidArgument, "invalid node id")
 	}
 	jkey, err := n.etcdJoinKeyPath()
-
+	if err != nil {
+		// This should never happen.
+		rpc.Trace(ctx).Printf("invalid join key representation: %v", err)
+		return status.Errorf(codes.InvalidArgument, "invalid join key representation")
+	}
 	// Delete both.
 	_, err = l.txnAsLeader(ctx,
 		clientv3.OpDelete(nkey),
diff --git a/metropolis/node/core/mgmt/svc_logs.go b/metropolis/node/core/mgmt/svc_logs.go
index b24e485..6566cee 100644
--- a/metropolis/node/core/mgmt/svc_logs.go
+++ b/metropolis/node/core/mgmt/svc_logs.go
@@ -169,7 +169,6 @@
 		if err != nil {
 			return err
 		}
-		chunk = make([]*cpb.LogEntry, 0, maxChunkSize)
 	}
 
 	// Start serving streaming data, if streaming has been requested.
diff --git a/metropolis/node/core/network/static.go b/metropolis/node/core/network/static.go
index a178e2c..6c72be5 100644
--- a/metropolis/node/core/network/static.go
+++ b/metropolis/node/core/network/static.go
@@ -168,6 +168,8 @@
 			for _, a := range i.Address {
 				ipNet, err := addressOrPrefix(a)
 				if err != nil {
+					l.Warningf("failed to parse %q as IPNet", a)
+					continue
 				}
 				if ipNet.IP.To4() != nil {
 					selectedAddr = ipNet.IP.To4()
diff --git a/metropolis/node/core/update/update.go b/metropolis/node/core/update/update.go
index ad4ad43..8490c78 100644
--- a/metropolis/node/core/update/update.go
+++ b/metropolis/node/core/update/update.go
@@ -275,6 +275,9 @@
 
 func (*Service) tryDownloadBundle(ctx context.Context, bundleURL string, bundleRaw *bytes.Buffer) error {
 	bundleReq, err := http.NewRequestWithContext(ctx, "GET", bundleURL, nil)
+	if err != nil {
+		return fmt.Errorf("failed to create request: %w", err)
+	}
 	bundleRes, err := http.DefaultClient.Do(bundleReq)
 	if err != nil {
 		return fmt.Errorf("HTTP request failed: %w", err)
diff --git a/metropolis/node/kubernetes/authproxy/authproxy.go b/metropolis/node/kubernetes/authproxy/authproxy.go
index e8e6fd8..c4a844e 100644
--- a/metropolis/node/kubernetes/authproxy/authproxy.go
+++ b/metropolis/node/kubernetes/authproxy/authproxy.go
@@ -56,6 +56,9 @@
 
 	k8sCAs := x509.NewCertPool()
 	cert, _, err := s.KPKI.Certificate(ctx, pki.IdCA)
+	if err != nil {
+		return fmt.Errorf("could not load certificate %q from PKI: %w", pki.IdCA, err)
+	}
 	parsedCert, err := x509.ParseCertificate(cert)
 	if err != nil {
 		return fmt.Errorf("failed to parse K8s CA certificate: %w", err)
diff --git a/metropolis/node/kubernetes/pki/kubernetes.go b/metropolis/node/kubernetes/pki/kubernetes.go
index a30aeda..66731ae 100644
--- a/metropolis/node/kubernetes/pki/kubernetes.go
+++ b/metropolis/node/kubernetes/pki/kubernetes.go
@@ -337,7 +337,7 @@
 	// Save to etcd.
 	_, err = k.KV.Put(ctx, path, string(key))
 	if err != nil {
-		err = fmt.Errorf("failed to write newly generated key: %w", err)
+		return nil, fmt.Errorf("failed to write newly generated key: %w", err)
 	}
 	return key, nil
 }
diff --git a/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go b/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
index bef049a..007bde6 100644
--- a/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
+++ b/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
@@ -158,6 +158,9 @@
 	}
 
 	kvmDevNode, err := deviceNumberFromString(string(kvmDevRaw))
+	if err != nil {
+		return fmt.Errorf("failed to parse KVM device node: %w", err)
+	}
 
 	err = unix.Mknod("/dev/kvm", 0660, int(kvmDevNode))
 	if err != nil && errors.Is(err, unix.EEXIST) {
diff --git a/metropolis/node/kubernetes/service_controller.go b/metropolis/node/kubernetes/service_controller.go
index ccb5b29..c1cec27 100644
--- a/metropolis/node/kubernetes/service_controller.go
+++ b/metropolis/node/kubernetes/service_controller.go
@@ -85,6 +85,9 @@
 	}
 
 	clientConfig, err := rawClientConfig.ClientConfig()
+	if err != nil {
+		return fmt.Errorf("could not fetch generate client config: %w", err)
+	}
 	clientSet, err := kubernetes.NewForConfig(clientConfig)
 	if err != nil {
 		return fmt.Errorf("could not generate kubernetes client: %w", err)
diff --git a/metropolis/node/kubernetes/service_worker.go b/metropolis/node/kubernetes/service_worker.go
index 2572dfa..7ad985f 100644
--- a/metropolis/node/kubernetes/service_worker.go
+++ b/metropolis/node/kubernetes/service_worker.go
@@ -238,6 +238,9 @@
 		return nil, nil, fmt.Errorf("could not generate kubernetes client config: %w", err)
 	}
 	clientConfig, err := rawClientConfig.ClientConfig()
+	if err != nil {
+		return nil, nil, fmt.Errorf("could not fetch generate client config: %w", err)
+	}
 	clientSet, err := kubernetes.NewForConfig(clientConfig)
 	if err != nil {
 		return nil, nil, fmt.Errorf("could not generate kubernetes client: %w", err)
diff --git a/metropolis/pkg/logtree/unraw/unraw_test.go b/metropolis/pkg/logtree/unraw/unraw_test.go
index 5526feb..71c88fd 100644
--- a/metropolis/pkg/logtree/unraw/unraw_test.go
+++ b/metropolis/pkg/logtree/unraw/unraw_test.go
@@ -112,6 +112,7 @@
 		close(started)
 		return r(ctx)
 	})
+	defer stop()
 
 	<-started
 
diff --git a/metropolis/pkg/tpm/tpm.go b/metropolis/pkg/tpm/tpm.go
index 7973399..2dbe6f6 100644
--- a/metropolis/pkg/tpm/tpm.go
+++ b/metropolis/pkg/tpm/tpm.go
@@ -160,6 +160,9 @@
 	}
 	tpmName := tpms[0]
 	ueventData, err := sysfs.ReadUevents(filepath.Join("/sys/class/tpm", tpmName, "uevent"))
+	if err != nil {
+		return fmt.Errorf("failed to read uevents: %w", err)
+	}
 	majorDev, err := strconv.Atoi(ueventData["MAJOR"])
 	if err != nil {
 		return fmt.Errorf("failed to convert uevent: %w", err)
diff --git a/version/stampgo/main.go b/version/stampgo/main.go
index 0ce658a..164e08a 100644
--- a/version/stampgo/main.go
+++ b/version/stampgo/main.go
@@ -147,6 +147,9 @@
 	}
 
 	versionBytes, err := proto.Marshal(version)
+	if err != nil {
+		log.Fatalf("failed to marshal version: %v", err)
+	}
 	literalBytes := make([]string, len(versionBytes))
 	for i, by := range versionBytes {
 		literalBytes[i] = fmt.Sprintf("0x%02x", by)