From 88c68456ee73a76a72f9c91f2821cddaca31c9e4 Mon Sep 17 00:00:00 2001 From: Richard Gee Date: Thu, 21 Nov 2024 10:42:34 +0000 Subject: [PATCH] feat: improve `install` error when app doesnt exist When trying to install an app that doesnt exist the error message would advise the user that the app doesnt exist and that they should run `install --help` to see what is available. However, there may be situations where the user is using the wrong verb because they are trying to get a tool, rather than an app. This change introduces a check when an app not found error is encountered to see whether a tool with the user provided name exists and advises them accordingly. also adds associated test. Signed-off-by: Richard Gee --- cmd/install.go | 15 +++++++- cmd/install_test.go | 91 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 cmd/install_test.go diff --git a/cmd/install.go b/cmd/install.go index f4075be8d..e6fa5abe2 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -4,14 +4,17 @@ package cmd import ( + "errors" "fmt" "os" "sort" + "strings" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" "github.com/alexellis/arkade/cmd/apps" + "github.com/alexellis/arkade/pkg/get" ) type ArkadeApp struct { @@ -100,7 +103,7 @@ To request a new app, raise a GitHub issue at: } } if app == nil { - return fmt.Errorf("no such app: %s, run \"arkade install --help\" for a list of apps", name) + return errors.New(checkForTool(name, get.MakeTools())) } return nil @@ -181,3 +184,13 @@ func NewArkadeApp(cmd func() *cobra.Command, msg string) ArkadeApp { InfoMessage: msg, } } + +func checkForTool(appName string, tools []get.Tool) string { + + for _, tool := range tools { + if strings.EqualFold(tool.Name, appName) { + return fmt.Sprintf("no such app. %s is available as a tool, run \"arkade get %s\" to get it", appName, appName) + } + } + return fmt.Sprintf("no such app: %s, run \"arkade install --help\" for a list of apps", appName) +} diff --git a/cmd/install_test.go b/cmd/install_test.go new file mode 100644 index 000000000..cd2588a56 --- /dev/null +++ b/cmd/install_test.go @@ -0,0 +1,91 @@ +// Copyright (c) arkade author(s) 2022. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +package cmd + +import ( + "testing" + + "github.com/alexellis/arkade/pkg/get" +) + +type Tool = get.Tool + +func TestCheckForTool(t *testing.T) { + tests := []struct { + name string + appName string + tools []Tool + expected string + expectFail bool + }{ + { + name: "Tool exists but expected is wrong", + appName: "kubectl", + tools: []Tool{ + {Name: "kubectl"}, + {Name: "helm"}, + {Name: "k9s"}, + }, + expected: "this test should fail", + expectFail: true, + }, + { + name: "Tool exists", + appName: "kubectl", + tools: []Tool{ + {Name: "kubectl"}, + {Name: "helm"}, + {Name: "k9s"}, + }, + expected: "no such app. kubectl is available as a tool, run \"arkade get kubectl\" to get it", + expectFail: false, + }, + { + name: "Tool does not exist", + appName: "randomtool", + tools: []Tool{ + {Name: "kubectl"}, + {Name: "helm"}, + }, + expected: "no such app: randomtool, run \"arkade install --help\" for a list of apps", + expectFail: false, + }, + { + name: "Case-insensitive match", + appName: "KUBECTL", + tools: []Tool{ + {Name: "kubectl"}, + {Name: "helm"}, + }, + expected: "no such app. KUBECTL is available as a tool, run \"arkade get KUBECTL\" to get it", + expectFail: false, + }, + { + name: "Empty tool list", + appName: "kubectl", + tools: []Tool{}, + expected: "no such app: kubectl, run \"arkade install --help\" for a list of apps", + expectFail: false, + }, + { + name: "Empty app name", + appName: "", + tools: []Tool{ + {Name: "kubectl"}, + }, + expected: "no such app: , run \"arkade install --help\" for a list of apps", + expectFail: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := checkForTool(tc.appName, tc.tools) + if result != tc.expected && !tc.expectFail { + t.Errorf("%s\nwant: %s\n got: %s", + tc.name, tc.expected, result) + } + }) + } +}