From 7e71782ba6d409f6caa1e4c598db0753666e97e1 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 20 Feb 2025 17:20:28 +0100 Subject: [PATCH] cli/command/context: fix error-handling of skip-tls-verify Before 2b9a4d5f4c9c4d749ecc208f34d212a2b1c45a08, this function would use "errors.Wrap" which returns nil if the original error was nil. fmt.Errorf does not do this, so without a nil check, it would unconditionally return an error; docker context create arm64 --docker host=ssh://172.17.101.26,skip-tls-verify=False unable to create docker endpoint config: name: %!w() Signed-off-by: Sebastiaan van Stijn --- cli/command/context/create_test.go | 49 ++++++++++++++++++++++++++++-- cli/command/context/options.go | 9 +++++- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/cli/command/context/create_test.go b/cli/command/context/create_test.go index 41e18f4804..a43404ad97 100644 --- a/cli/command/context/create_test.go +++ b/cli/command/context/create_test.go @@ -59,42 +59,87 @@ func TestCreate(t *testing.T) { cli := makeFakeCli(t) assert.NilError(t, cli.ContextStore().CreateOrUpdate(store.Metadata{Name: "existing-context"})) tests := []struct { + doc string options CreateOptions expecterErr string }{ { + doc: "empty name", expecterErr: `context name cannot be empty`, }, { + doc: "reserved name", options: CreateOptions{ Name: "default", }, expecterErr: `"default" is a reserved context name`, }, { + doc: "whitespace-only name", options: CreateOptions{ Name: " ", }, expecterErr: `context name " " is invalid`, }, { + doc: "existing context", options: CreateOptions{ Name: "existing-context", }, expecterErr: `context "existing-context" already exists`, }, { + doc: "invalid docker host", options: CreateOptions{ Name: "invalid-docker-host", Docker: map[string]string{ - keyHost: "some///invalid/host", + "host": "some///invalid/host", }, }, expecterErr: `unable to parse docker host`, }, + { + doc: "ssh host with skip-tls-verify=false", + options: CreateOptions{ + Name: "skip-tls-verify-false", + Docker: map[string]string{ + "host": "ssh://example.com,skip-tls-verify=false", + }, + }, + }, + { + doc: "ssh host with skip-tls-verify=true", + options: CreateOptions{ + Name: "skip-tls-verify-true", + Docker: map[string]string{ + "host": "ssh://example.com,skip-tls-verify=true", + }, + }, + }, + { + doc: "ssh host with skip-tls-verify=INVALID", + options: CreateOptions{ + Name: "skip-tls-verify-invalid", + Docker: map[string]string{ + "host": "ssh://example.com", + "skip-tls-verify": "INVALID", + }, + }, + expecterErr: `unable to create docker endpoint config: skip-tls-verify: parsing "INVALID": invalid syntax`, + }, + { + doc: "unknown option", + options: CreateOptions{ + Name: "unknown-option", + Docker: map[string]string{ + "UNKNOWN": "value", + }, + }, + expecterErr: `unable to create docker endpoint config: unrecognized config key: UNKNOWN`, + }, } for _, tc := range tests { - t.Run(tc.options.Name, func(t *testing.T) { + t.Run(tc.doc, func(t *testing.T) { err := RunCreate(cli, &tc.options) if tc.expecterErr == "" { assert.NilError(t, err) diff --git a/cli/command/context/options.go b/cli/command/context/options.go index b2c8a4b832..7b0d4aac92 100644 --- a/cli/command/context/options.go +++ b/cli/command/context/options.go @@ -68,7 +68,14 @@ func parseBool(config map[string]string, name string) (bool, error) { return false, nil } res, err := strconv.ParseBool(strVal) - return res, fmt.Errorf("name: %w", err) + if err != nil { + var nErr *strconv.NumError + if errors.As(err, &nErr) { + return res, fmt.Errorf("%s: parsing %q: %w", name, nErr.Num, nErr.Err) + } + return res, fmt.Errorf("%s: %w", name, err) + } + return res, nil } func validateConfig(config map[string]string, allowedKeys map[string]struct{}) error {