metropolis/cli/metroctl: refactor to use RunE instead of log.Fatal

Change-Id: Id5ca65980816e1715a8f08afcdf712292117012a
Reviewed-on: https://review.monogon.dev/c/monogon/+/3441
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/cli/metroctl/rpc.go b/metropolis/cli/metroctl/rpc.go
index 512cb98..cfe1b41 100644
--- a/metropolis/cli/metroctl/rpc.go
+++ b/metropolis/cli/metroctl/rpc.go
@@ -5,7 +5,7 @@
 	"crypto/tls"
 	"crypto/x509"
 	"errors"
-	"log"
+	"fmt"
 	"net"
 	"net/http"
 
@@ -17,23 +17,23 @@
 	"source.monogon.dev/metropolis/node/core/rpc/resolver"
 )
 
-func dialAuthenticated(ctx context.Context) *grpc.ClientConn {
+func dialAuthenticated(ctx context.Context) (*grpc.ClientConn, error) {
 	// Collect credentials, validate command parameters, and try dialing the
 	// cluster.
 	ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
 	if errors.Is(err, core.ErrNoCredentials) {
-		log.Fatalf("You have to take ownership of the cluster first: %v", err)
+		return nil, fmt.Errorf("you have to take ownership of the cluster first: %w", err)
 	}
 	if err != nil {
-		log.Fatalf("Failed to get owner credentials: %v", err)
+		return nil, fmt.Errorf("failed to get owner credentials: %w", err)
 	}
 	if len(flags.clusterEndpoints) == 0 {
-		log.Fatal("Please provide at least one cluster endpoint using the --endpoint parameter.")
+		return nil, fmt.Errorf("please provide at least one cluster endpoint using the --endpoint parameter")
 	}
 
 	ca, err := core.GetClusterCAWithTOFU(ctx, connectOptions())
 	if err != nil {
-		log.Fatalf("Failed to get cluster CA: %v", err)
+		return nil, fmt.Errorf("failed to get cluster CA: %w", err)
 	}
 
 	tlsc := tls.Certificate{
@@ -43,39 +43,39 @@
 	creds := rpc.NewAuthenticatedCredentials(tlsc, rpc.WantRemoteCluster(ca))
 	opts, err := core.DialOpts(ctx, connectOptions())
 	if err != nil {
-		log.Fatalf("While configuring dial options: %v", err)
+		return nil, fmt.Errorf("while configuring dial options: %w", err)
 	}
 	opts = append(opts, grpc.WithTransportCredentials(creds))
 
 	cc, err := grpc.Dial(resolver.MetropolisControlAddress, opts...)
 	if err != nil {
-		log.Fatalf("While dialing cluster: %v", err)
+		return nil, fmt.Errorf("while dialing cluster: %w", err)
 	}
-	return cc
+	return cc, nil
 }
 
-func dialAuthenticatedNode(ctx context.Context, id, address string, cacert *x509.Certificate) *grpc.ClientConn {
+func dialAuthenticatedNode(ctx context.Context, id, address string, cacert *x509.Certificate) (*grpc.ClientConn, error) {
 	// Collect credentials, validate command parameters, and try dialing the
 	// cluster.
 	ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
 	if errors.Is(err, core.ErrNoCredentials) {
-		log.Fatalf("You have to take ownership of the cluster first: %v", err)
+		return nil, fmt.Errorf("you have to take ownership of the cluster first: %w", err)
 	}
 	cc, err := core.DialNode(ctx, opkey, ocert, cacert, flags.proxyAddr, id, address)
 	if err != nil {
-		log.Fatalf("While dialing node: %v", err)
+		return nil, fmt.Errorf("while dialing node: %w", err)
 	}
-	return cc
+	return cc, nil
 }
 
-func newAuthenticatedNodeHTTPTransport(ctx context.Context, id string) *http.Transport {
+func newAuthenticatedNodeHTTPTransport(ctx context.Context, id string) (*http.Transport, error) {
 	cacert, err := core.GetClusterCAWithTOFU(ctx, connectOptions())
 	if err != nil {
-		log.Fatalf("Could not get CA certificate: %v", err)
+		return nil, fmt.Errorf("could not get CA certificate: %w", err)
 	}
 	ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
 	if errors.Is(err, core.ErrNoCredentials) {
-		log.Fatalf("You have to take ownership of the cluster first: %v", err)
+		return nil, fmt.Errorf("you have to take ownership of the cluster first: %w", err)
 	}
 	tlsc := tls.Certificate{
 		Certificate: [][]byte{ocert.Raw},
@@ -88,12 +88,12 @@
 	if flags.proxyAddr != "" {
 		dialer, err := proxy.SOCKS5("tcp", flags.proxyAddr, nil, proxy.Direct)
 		if err != nil {
-			log.Fatalf("Failed to create proxy dialer: %v", err)
+			return nil, fmt.Errorf("failed to create proxy dialer: %w", err)
 		}
 		transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
 			// TODO(q3k): handle context
 			return dialer.Dial(network, addr)
 		}
 	}
-	return transport
+	return transport, nil
 }