From c47a1b1e550a361a009156e14fcc933dfbbdee64 Mon Sep 17 00:00:00 2001
From: Jordan Christiansen <xordspar0@gmail.com>
Date: Thu, 8 Oct 2020 12:07:42 -0500
Subject: Fix the "err: cause" order of OCI runtime errors

Previously, the order of OCI error messages was reversed, so that the
type of error was listed as the cause. For example:

    Error: writing file `cpu.cfs_quota_us`: Invalid argument: OCI runtime error

This error message makes it seem like "OCI runtime error" is the
argument that was invalid. In fact, "OCI runtime error" is the error and
"writing file ..." is the cause. With this change, the above message
reads:

    Error: OCI runtime error: writing file `cpu.cfs_quota_us`: Invalid argument

Signed-off-by: Jordan Christiansen <xordspar0@gmail.com>
---
 cmd/podman/root.go      | 19 ++++++++++++++++++-
 cmd/podman/root_test.go | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 cmd/podman/root_test.go

(limited to 'cmd/podman')

diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 1e73f7540..6293fa17d 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -11,6 +11,7 @@ import (
 	"github.com/containers/common/pkg/config"
 	"github.com/containers/podman/v2/cmd/podman/registry"
 	"github.com/containers/podman/v2/cmd/podman/validate"
+	"github.com/containers/podman/v2/libpod/define"
 	"github.com/containers/podman/v2/pkg/domain/entities"
 	"github.com/containers/podman/v2/pkg/parallel"
 	"github.com/containers/podman/v2/pkg/rootless"
@@ -84,7 +85,7 @@ func init() {
 
 func Execute() {
 	if err := rootCmd.ExecuteContext(registry.GetContextWithOptions()); err != nil {
-		fmt.Fprintln(os.Stderr, "Error:", err.Error())
+		fmt.Fprintln(os.Stderr, formatError(err))
 	} else if registry.GetExitCode() == registry.ExecErrorCodeGeneric {
 		// The exitCode modified from registry.ExecErrorCodeGeneric,
 		// indicates an application
@@ -331,3 +332,19 @@ func resolveDestination() (string, string, string) {
 	}
 	return cfg.Engine.ActiveService, uri, ident
 }
+
+func formatError(err error) string {
+	var message string
+	if errors.Cause(err) == define.ErrOCIRuntime {
+		// OCIRuntimeErrors include the reason for the failure in the
+		// second to last message in the error chain.
+		message = fmt.Sprintf(
+			"Error: %s: %s",
+			define.ErrOCIRuntime.Error(),
+			strings.TrimSuffix(err.Error(), ": "+define.ErrOCIRuntime.Error()),
+		)
+	} else {
+		message = "Error: " + err.Error()
+	}
+	return message
+}
diff --git a/cmd/podman/root_test.go b/cmd/podman/root_test.go
new file mode 100644
index 000000000..0473128df
--- /dev/null
+++ b/cmd/podman/root_test.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+
+	"github.com/containers/podman/v2/libpod/define"
+	"github.com/pkg/errors"
+)
+
+func TestFormatError(t *testing.T) {
+	err := errors.New("unknown error")
+	output := formatError(err)
+	expected := fmt.Sprintf("Error: %v", err)
+
+	if output != expected {
+		t.Errorf("Expected \"%s\" to equal \"%s\"", output, err.Error())
+	}
+}
+
+func TestFormatOCIError(t *testing.T) {
+	expectedPrefix := "Error: "
+	expectedSuffix := "OCI runtime output"
+	err := errors.Wrap(define.ErrOCIRuntime, expectedSuffix)
+	output := formatError(err)
+
+	if !strings.HasPrefix(output, expectedPrefix) {
+		t.Errorf("Expected \"%s\" to start with \"%s\"", output, expectedPrefix)
+	}
+	if !strings.HasSuffix(output, expectedSuffix) {
+		t.Errorf("Expected \"%s\" to end with \"%s\"", output, expectedSuffix)
+	}
+}
-- 
cgit v1.2.3-54-g00ecf