diff --git a/docs/cmd/kn.md b/docs/cmd/kn.md index 5c030706c9..ef3f3b7c38 100644 --- a/docs/cmd/kn.md +++ b/docs/cmd/kn.md @@ -13,10 +13,10 @@ Eventing: Manage event subscriptions and channels. Connect up event sources. ### Options ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) -h, --help help for kn --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_completion.md b/docs/cmd/kn_completion.md index 152e777efb..7d539d9079 100644 --- a/docs/cmd/kn_completion.md +++ b/docs/cmd/kn_completion.md @@ -20,9 +20,9 @@ kn completion [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_plugin.md b/docs/cmd/kn_plugin.md index e9705ede50..4e18c72f9c 100644 --- a/docs/cmd/kn_plugin.md +++ b/docs/cmd/kn_plugin.md @@ -4,9 +4,9 @@ Plugin command group ### Synopsis -Provides utilities for interacting with kn plugins. +Provides utilities for interacting and managing with kn plugins. -Plugins provide extended functionality that is not part of the major kn command-line distribution. +Plugins provide extended functionality that is not part of the core kn command-line distribution. Please refer to the documentation and examples for more information about how write your own plugins. ``` @@ -22,9 +22,9 @@ kn plugin [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_plugin_list.md b/docs/cmd/kn_plugin_list.md index 62683dcabc..8c65db58ee 100644 --- a/docs/cmd/kn_plugin_list.md +++ b/docs/cmd/kn_plugin_list.md @@ -6,12 +6,12 @@ List all visible plugin executables List all visible plugin executables. - Available plugin files are those that are: - - executable - - begin with "kn- - - anywhere on the path specfied in Kn's config pluginDir variable, which: - * defaults to $PATH if not specified - * can be overridden with the --plugin-dir flag +Available plugin files are those that are: +- executable +- begin with "kn- +- anywhere on the path specfied in Kn's config pluginDir variable, which: + * defaults to $PATH if not specified + * can be overridden with the --plugin-dir flag ``` kn plugin list [flags] @@ -27,9 +27,9 @@ kn plugin list [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_revision.md b/docs/cmd/kn_revision.md index 07341ecabb..8377747714 100644 --- a/docs/cmd/kn_revision.md +++ b/docs/cmd/kn_revision.md @@ -19,9 +19,9 @@ kn revision [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_revision_delete.md b/docs/cmd/kn_revision_delete.md index 7c34a2bd65..7149c9c515 100644 --- a/docs/cmd/kn_revision_delete.md +++ b/docs/cmd/kn_revision_delete.md @@ -28,9 +28,9 @@ kn revision delete NAME [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_revision_describe.md b/docs/cmd/kn_revision_describe.md index d8ab6443f9..42a9924ca0 100644 --- a/docs/cmd/kn_revision_describe.md +++ b/docs/cmd/kn_revision_describe.md @@ -23,9 +23,9 @@ kn revision describe NAME [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_revision_list.md b/docs/cmd/kn_revision_list.md index 54639ed802..81876e45e1 100644 --- a/docs/cmd/kn_revision_list.md +++ b/docs/cmd/kn_revision_list.md @@ -36,9 +36,9 @@ kn revision list [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_route.md b/docs/cmd/kn_route.md index 18a5714406..2889fa6206 100644 --- a/docs/cmd/kn_route.md +++ b/docs/cmd/kn_route.md @@ -19,9 +19,9 @@ kn route [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_route_list.md b/docs/cmd/kn_route_list.md index e3d513fe53..9a25504e6c 100644 --- a/docs/cmd/kn_route_list.md +++ b/docs/cmd/kn_route_list.md @@ -38,9 +38,9 @@ kn route list NAME [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_service.md b/docs/cmd/kn_service.md index bad1046087..38f877bb84 100644 --- a/docs/cmd/kn_service.md +++ b/docs/cmd/kn_service.md @@ -19,9 +19,9 @@ kn service [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_service_create.md b/docs/cmd/kn_service_create.md index 382612d032..b8978b4aa8 100644 --- a/docs/cmd/kn_service_create.md +++ b/docs/cmd/kn_service_create.md @@ -60,9 +60,9 @@ kn service create NAME --image IMAGE [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_service_delete.md b/docs/cmd/kn_service_delete.md index 710d7dca20..b67b67bc2c 100644 --- a/docs/cmd/kn_service_delete.md +++ b/docs/cmd/kn_service_delete.md @@ -31,9 +31,9 @@ kn service delete NAME [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_service_describe.md b/docs/cmd/kn_service_describe.md index aa93c1bb5d..51a7fe75b7 100644 --- a/docs/cmd/kn_service_describe.md +++ b/docs/cmd/kn_service_describe.md @@ -23,9 +23,9 @@ kn service describe NAME [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_service_list.md b/docs/cmd/kn_service_list.md index b995e7f05d..e83febc3c3 100644 --- a/docs/cmd/kn_service_list.md +++ b/docs/cmd/kn_service_list.md @@ -24,9 +24,9 @@ kn service list [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_service_update.md b/docs/cmd/kn_service_update.md index b65abeb498..be89c2b3a4 100644 --- a/docs/cmd/kn_service_update.md +++ b/docs/cmd/kn_service_update.md @@ -45,9 +45,9 @@ kn service update NAME [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/docs/cmd/kn_version.md b/docs/cmd/kn_version.md index 0c3c599d83..f1589fa058 100644 --- a/docs/cmd/kn_version.md +++ b/docs/cmd/kn_version.md @@ -19,9 +19,9 @@ kn version [flags] ### Options inherited from parent commands ``` - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) - --plugin-dir string kn plugin directory (default is value in kn config or $PATH) (default "$PATH") + --plugin-dir string kn plugin directory also stored in kn config (default "$PATH") ``` ### SEE ALSO diff --git a/pkg/kn/commands/completion_test.go b/pkg/kn/commands/completion_test.go new file mode 100644 index 0000000000..f108c74220 --- /dev/null +++ b/pkg/kn/commands/completion_test.go @@ -0,0 +1,62 @@ +// Copyright © 2018 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package commands + +import ( + "testing" + + "github.com/spf13/cobra" + "gotest.tools/assert" +) + +func TestCompletion(t *testing.T) { + var ( + fakeRootCmd, completionCmd *cobra.Command + knParams *KnParams + ) + + setup := func() { + knParams = &KnParams{} + completionCmd = NewCompletionCommand(knParams) + + fakeRootCmd = &cobra.Command{} + fakeRootCmd.AddCommand(completionCmd) + } + + t.Run("creates a CompletionCommand", func(t *testing.T) { + setup() + assert.Equal(t, completionCmd.Use, "completion") + assert.Equal(t, completionCmd.Short, "Output shell completion code (default Bash)") + assert.Assert(t, completionCmd.RunE == nil) + }) + + t.Run("returns completion code for BASH", func(t *testing.T) { + setup() + CaptureStdout(t) + defer ReleaseStdout(t) + + completionCmd.Run(fakeRootCmd, []string{}) + assert.Assert(t, ReadStdout(t) != "") + }) + + t.Run("returns completion code for ZSH", func(t *testing.T) { + setup() + CaptureStdout(t) + defer ReleaseStdout(t) + + completionCmd.Run(fakeRootCmd, []string{"--zsh"}) + assert.Assert(t, ReadStdout(t) != "") + }) +} diff --git a/pkg/kn/commands/plugin/path_verifier_test.go b/pkg/kn/commands/plugin/path_verifier_test.go index 159d09940e..9e8b29fe13 100644 --- a/pkg/kn/commands/plugin/path_verifier_test.go +++ b/pkg/kn/commands/plugin/path_verifier_test.go @@ -30,7 +30,7 @@ var ( verifier *CommandOverrideVerifier ) -var setup = func() { +var setup = func(t *testing.T) { knParams := &commands.KnParams{} rootCmd, _, _ = commands.CreateTestKnCommand(NewPluginCommand(knParams), knParams) verifier = &CommandOverrideVerifier{ @@ -47,7 +47,7 @@ var cleanup = func(t *testing.T) { func TestCommandOverrideVerifier_Verify_with_nil_root_command(t *testing.T) { t.Run("returns error verifying path", func(t *testing.T) { - setup() + setup(t) defer cleanup(t) verifier.Root = nil @@ -60,7 +60,7 @@ func TestCommandOverrideVerifier_Verify_with_nil_root_command(t *testing.T) { func TestCommandOverrideVerifier_Verify_with_root_command(t *testing.T) { t.Run("when plugin in path not executable", func(t *testing.T) { - setup() + setup(t) defer cleanup(t) pluginPath = CreateTestPlugin(t, KnTestPluginName, KnTestPluginScript, FileModeReadable) @@ -74,7 +74,7 @@ func TestCommandOverrideVerifier_Verify_with_root_command(t *testing.T) { }) t.Run("when kn plugin in path is executable", func(t *testing.T) { - setup() + setup(t) defer cleanup(t) pluginPath = CreateTestPlugin(t, KnTestPluginName, KnTestPluginScript, FileModeExecutable) @@ -94,7 +94,7 @@ func TestCommandOverrideVerifier_Verify_with_root_command(t *testing.T) { }) t.Run("when kn plugin in path overwrites existing command", func(t *testing.T) { - setup() + setup(t) defer cleanup(t) var overwritingPluginPath = CreateTestPlugin(t, "kn-plugin", KnTestPluginScript, FileModeExecutable) defer DeleteTestPlugin(t, overwritingPluginPath) diff --git a/pkg/kn/commands/plugin/plugin.go b/pkg/kn/commands/plugin/plugin.go index 5efb8d776d..04362aa780 100644 --- a/pkg/kn/commands/plugin/plugin.go +++ b/pkg/kn/commands/plugin/plugin.go @@ -23,9 +23,9 @@ func NewPluginCommand(p *commands.KnParams) *cobra.Command { pluginCmd := &cobra.Command{ Use: "plugin", Short: "Plugin command group", - Long: `Provides utilities for interacting with kn plugins. + Long: `Provides utilities for interacting and managing with kn plugins. -Plugins provide extended functionality that is not part of the major kn command-line distribution. +Plugins provide extended functionality that is not part of the core kn command-line distribution. Please refer to the documentation and examples for more information about how write your own plugins.`, } pluginCmd.AddCommand(NewPluginListCommand(p)) diff --git a/pkg/kn/commands/plugin/plugin_handler_test.go b/pkg/kn/commands/plugin/plugin_handler_test.go new file mode 100644 index 0000000000..691e19065f --- /dev/null +++ b/pkg/kn/commands/plugin/plugin_handler_test.go @@ -0,0 +1,126 @@ +// Copyright © 2018 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "gotest.tools/assert" +) + +func TestPluginHandler(t *testing.T) { + var ( + pluginHandler PluginHandler + pluginPath, pluginName, tmpPathDir string + err error + ) + + setup := func(t *testing.T) { + pluginHandler = &DefaultPluginHandler{ + ValidPrefixes: []string{"kn"}, + } + assert.Assert(t, pluginHandler != nil) + + tmpPathDir, err = ioutil.TempDir("", "plugin_list") + assert.Assert(t, err == nil) + } + + cleanup := func(t *testing.T) { + err = os.RemoveAll(tmpPathDir) + assert.Assert(t, err == nil) + } + + beforeEach := func(t *testing.T) { + pluginName = "fake-plugin-name" + pluginPath = CreateTestPluginInPath(t, "kn-"+pluginName, KnTestPluginScript, FileModeExecutable, tmpPathDir) + assert.Assert(t, pluginPath != "") + + err = os.Setenv("PATH", tmpPathDir) + assert.Assert(t, err == nil) + } + + t.Run("#NewDefaultPluginHandler", func(t *testing.T) { + setup(t) + defer cleanup(t) + + pHandler := NewDefaultPluginHandler([]string{"kn"}) + assert.Assert(t, pHandler != nil) + }) + + t.Run("#Lookup", func(t *testing.T) { + t.Run("returns the first filepath matching prefix", func(t *testing.T) { + setup(t) + defer cleanup(t) + beforeEach(t) + + path, exists := pluginHandler.Lookup(pluginName) + assert.Assert(t, path != "", fmt.Sprintf("no path when Lookup(%s)", pluginName)) + assert.Assert(t, exists == true, fmt.Sprintf("could not Lookup(%s)", pluginName)) + }) + + t.Run("returns empty filepath when no matching prefix found", func(t *testing.T) { + setup(t) + defer cleanup(t) + + path, exists := pluginHandler.Lookup("bogus-plugin-name") + assert.Assert(t, path == "", fmt.Sprintf("unexpected plugin: kn-bogus-plugin-name")) + assert.Assert(t, exists == false, fmt.Sprintf("unexpected plugin: kn-bogus-plugin-name")) + }) + }) + + t.Run("#Execute", func(t *testing.T) { + t.Run("success while executing the executable with args and environment", func(t *testing.T) { + setup(t) + defer cleanup(t) + beforeEach(t) + + err = pluginHandler.Execute(pluginPath, []string{pluginPath}, os.Environ()) + assert.Assert(t, err == nil, fmt.Sprintf("test plugin %s failed executing", pluginName)) + }) + + t.Run("fails while executing the executable with args and environment", func(t *testing.T) { + setup(t) + defer cleanup(t) + beforeEach(t) + + bogusPath := filepath.Join(filepath.Dir(pluginPath), "kn-bogus-plugin-name") + err = pluginHandler.Execute(bogusPath, []string{bogusPath}, os.Environ()) + assert.Assert(t, err != nil, fmt.Sprintf("bogus plugin in path %s unexpectedly executed OK", bogusPath)) + }) + }) + + t.Run("HandlePluginCommand", func(t *testing.T) { + t.Run("sucess handling", func(t *testing.T) { + setup(t) + defer cleanup(t) + beforeEach(t) + + err = HandlePluginCommand(pluginHandler, []string{pluginPath, pluginName}) + assert.Assert(t, err == nil, fmt.Sprintf("test plugin %s failed executing", pluginName)) + }) + + t.Run("fails handling", func(t *testing.T) { + setup(t) + defer cleanup(t) + + err = HandlePluginCommand(pluginHandler, []string{pluginPath, "kn-bogus-plugin-name"}) + assert.Assert(t, err != nil, fmt.Sprintf("test plugin %s expected to fail executing", pluginName)) + }) + }) +} diff --git a/pkg/kn/commands/plugin/plugin_list.go b/pkg/kn/commands/plugin/plugin_list.go index e751ca242f..f98dab7e74 100644 --- a/pkg/kn/commands/plugin/plugin_list.go +++ b/pkg/kn/commands/plugin/plugin_list.go @@ -45,12 +45,12 @@ func NewPluginListCommand(p *commands.KnParams) *cobra.Command { Short: "List all visible plugin executables", Long: `List all visible plugin executables. - Available plugin files are those that are: - - executable - - begin with "kn- - - anywhere on the path specfied in Kn's config pluginDir variable, which: - * defaults to $PATH if not specified - * can be overridden with the --plugin-dir flag`, +Available plugin files are those that are: +- executable +- begin with "kn- +- anywhere on the path specfied in Kn's config pluginDir variable, which: + * defaults to $PATH if not specified + * can be overridden with the --plugin-dir flag`, RunE: func(cmd *cobra.Command, args []string) error { err := pluginFlags.complete(cmd) if err != nil { diff --git a/pkg/kn/commands/plugin/plugin_test.go b/pkg/kn/commands/plugin/plugin_test.go index 4ef968041b..b5538cdcb2 100644 --- a/pkg/kn/commands/plugin/plugin_test.go +++ b/pkg/kn/commands/plugin/plugin_test.go @@ -39,7 +39,7 @@ Flags: -h, --help help for plugin Global Flags: - --config string config file (default is $HOME/.kn/config.yaml) + --config string kn config file (default is $HOME/.kn/config.yaml) --kubeconfig string kubectl config file (default is $HOME/.kube/config) --plugin-dir string kn plugin directory (default is value in kn config or $PATH) diff --git a/pkg/kn/commands/plugin/plugin_test_helper.go b/pkg/kn/commands/plugin/plugin_test_helper.go index 364fd957fd..095492151e 100644 --- a/pkg/kn/commands/plugin/plugin_test_helper.go +++ b/pkg/kn/commands/plugin/plugin_test_helper.go @@ -31,7 +31,7 @@ const ( echo "I am a test Kn plugin" ` FileModeReadable = 0644 - FileModeExecutable = 777 + FileModeExecutable = 0777 ) // FindSubCommand return the sub-command by name diff --git a/pkg/kn/commands/test_helper.go b/pkg/kn/commands/testing_helper.go similarity index 92% rename from pkg/kn/commands/test_helper.go rename to pkg/kn/commands/testing_helper.go index 7833ec7100..5f09e71d15 100644 --- a/pkg/kn/commands/test_helper.go +++ b/pkg/kn/commands/testing_helper.go @@ -19,7 +19,6 @@ import ( "flag" "io" "os" - "strings" "testing" "github.com/knative/client/pkg/serving/v1alpha1" @@ -55,16 +54,6 @@ func CreateTestKnCommand(cmd *cobra.Command, knParams *KnParams) (*cobra.Command return knCommand, fakeServing, buf } -// TestContains is a test helper function, checking if a substring is present in given -// output string -func TestContains(t *testing.T, output string, sub []string, element string) { - for _, each := range sub { - if !strings.Contains(output, each) { - t.Errorf("Missing %s: %s", element, each) - } - } -} - // CaptureStdout collects the current content of os.Stdout func CaptureStdout(t *testing.T) { oldStdout = os.Stdout diff --git a/pkg/kn/commands/testing_helper_test.go b/pkg/kn/commands/testing_helper_test.go new file mode 100644 index 0000000000..fdbe59448b --- /dev/null +++ b/pkg/kn/commands/testing_helper_test.go @@ -0,0 +1,56 @@ +// Copyright © 2018 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package commands + +import ( + "bytes" + "strings" + "testing" + + "github.com/knative/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1/fake" + "github.com/spf13/cobra" + "gotest.tools/assert" +) + +func TestCreateTestKnCommand(t *testing.T) { + var ( + knCmd *cobra.Command + serving *fake.FakeServingV1alpha1 + buffer *bytes.Buffer + ) + + setup := func(t *testing.T) { + knParams := &KnParams{} + knCmd, serving, buffer = CreateTestKnCommand(&cobra.Command{Use: "fake"}, knParams) + assert.Assert(t, knCmd != nil) + assert.Assert(t, len(knCmd.Commands()) == 1) + assert.Assert(t, knCmd.Commands()[0].Use == "fake") + assert.Assert(t, serving != nil) + assert.Assert(t, buffer != nil) + } + + t.Run("creates a new kn cobra.Command", func(t *testing.T) { + setup(t) + + assert.Assert(t, knCmd != nil) + assert.Assert(t, knCmd.Use == "kn") + assert.Assert(t, knCmd.Short == "Knative client") + assert.Assert(t, strings.Contains(knCmd.Long, "Manage your Knative building blocks:")) + assert.Assert(t, knCmd.RunE == nil) + assert.Assert(t, knCmd.DisableAutoGenTag == true) + assert.Assert(t, knCmd.SilenceUsage == true) + assert.Assert(t, knCmd.SilenceErrors == true) + }) +} diff --git a/pkg/kn/commands/version_test.go b/pkg/kn/commands/version_test.go new file mode 100644 index 0000000000..921b67ea0d --- /dev/null +++ b/pkg/kn/commands/version_test.go @@ -0,0 +1,103 @@ +// Copyright © 2018 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package commands + +import ( + "bytes" + "testing" + "text/template" + + "github.com/spf13/cobra" + "gotest.tools/assert" +) + +type versionOutput struct { + Version string + BuildDate string + GitRevision string + ServingVersion string +} + +var versionOutputTemplate = `Version: {{.Version}} +Build Date: {{.BuildDate}} +Git Revision: {{.GitRevision}} +Dependencies: +- serving: {{.ServingVersion}} +` + +const ( + fakeVersion = "fake-version" + fakeBuildDate = "fake-build-date" + fakeGitRevision = "fake-git-revision" + fakeServingVersion = "fake-serving-version" +) + +func TestVersion(t *testing.T) { + var ( + versionCmd *cobra.Command + knParams *KnParams + expectedVersionOutput string + ) + + setup := func() { + Version = fakeVersion + BuildDate = fakeBuildDate + GitRevision = fakeGitRevision + ServingVersion = fakeServingVersion + + expectedVersionOutput = genVersionOuput(t, versionOutputTemplate, + versionOutput{ + Version: fakeVersion, + BuildDate: fakeBuildDate, + GitRevision: fakeGitRevision, + ServingVersion: fakeServingVersion}) + + knParams = &KnParams{} + versionCmd = NewVersionCommand(knParams) + } + + t.Run("creates a VersionCommand", func(t *testing.T) { + setup() + CaptureStdout(t) + defer ReleaseStdout(t) + + assert.Equal(t, versionCmd.Use, "version") + assert.Equal(t, versionCmd.Short, "Prints the client version") + assert.Assert(t, versionCmd.RunE != nil) + }) + + t.Run("prints version, build date, git revision, and serving version string", func(t *testing.T) { + setup() + CaptureStdout(t) + defer ReleaseStdout(t) + + err := versionCmd.RunE(nil, []string{}) + assert.Assert(t, err == nil) + assert.Equal(t, ReadStdout(t), expectedVersionOutput) + }) +} + +// Private + +func genVersionOuput(t *testing.T, templ string, vOutput versionOutput) string { + tmpl, err := template.New("versionOutput").Parse(versionOutputTemplate) + assert.Assert(t, err == nil) + + buf := bytes.Buffer{} + err = tmpl.Execute(&buf, vOutput) + assert.Assert(t, err == nil) + + return buf.String() +} diff --git a/pkg/kn/core/root.go b/pkg/kn/core/root.go index 04b6c2a1e8..f62e14fedf 100644 --- a/pkg/kn/core/root.go +++ b/pkg/kn/core/root.go @@ -98,8 +98,8 @@ Eventing: Manage event subscriptions and channels. Connect up event sources.`, } // Persistent flags - rootCmd.PersistentFlags().StringVar(&commands.CfgFile, "config", "", "config file (default is $HOME/.kn/config.yaml)") - rootCmd.PersistentFlags().StringVar(&commands.PluginDir, "plugin-dir", "$PATH", "kn plugin directory (default is value in kn config or $PATH)") + rootCmd.PersistentFlags().StringVar(&commands.CfgFile, "config", "", "kn config file (default is $HOME/.kn/config.yaml)") + rootCmd.PersistentFlags().StringVar(&commands.PluginDir, "plugin-dir", "$PATH", "kn plugin directory also stored in kn config") rootCmd.PersistentFlags().StringVar(&p.KubeCfgPath, "kubeconfig", "", "kubectl config file (default is $HOME/.kube/config)") // bind and set default with viper @@ -171,6 +171,6 @@ func initConfig() { // If a config file is found, read it in. if err := viper.ReadInConfig(); err == nil { - fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) + fmt.Fprintln(os.Stderr, "Using kn config file:", viper.ConfigFileUsed()) } } diff --git a/pkg/kn/core/root_test.go b/pkg/kn/core/root_test.go index 32bf6fd073..e6f55da1ab 100644 --- a/pkg/kn/core/root_test.go +++ b/pkg/kn/core/root_test.go @@ -15,52 +15,123 @@ package core import ( + "io/ioutil" + "os" "strings" "testing" "github.com/knative/client/pkg/kn/commands" + "github.com/knative/client/pkg/kn/commands/plugin" "github.com/spf13/cobra" "gotest.tools/assert" ) -func TestNewKnCommand(t *testing.T) { +func TestNewDefaultKnCommand(t *testing.T) { var rootCmd *cobra.Command - setup := func() { - rootCmd = NewKnCommand(commands.KnParams{}) + setup := func(t *testing.T) { + rootCmd = NewDefaultKnCommand() } - setup() - t.Run("returns a valid root command", func(t *testing.T) { - assert.Assert(t, rootCmd != nil) + setup(t) + + checkRootCmd(t, rootCmd) + }) +} + +func TestNewDefaultKnCommandWithArgs(t *testing.T) { + var ( + rootCmd *cobra.Command + pluginHandler plugin.PluginHandler + args []string + ) + + setup := func(t *testing.T) { + rootCmd = NewDefaultKnCommandWithArgs(pluginHandler, args, os.Stdin, os.Stdout, os.Stderr) + } + + t.Run("when pluginHandler is nil", func(t *testing.T) { + args = []string{} + setup(t) + + t.Run("returns a valid root command", func(t *testing.T) { + checkRootCmd(t, rootCmd) + }) + }) + + t.Run("when pluginHandler is not nil", func(t *testing.T) { + t.Run("when args empty", func(t *testing.T) { + args = []string{} + setup(t) + + t.Run("returns a valid root command", func(t *testing.T) { + checkRootCmd(t, rootCmd) + }) + }) + + t.Run("when args not empty", func(t *testing.T) { + var ( + pluginName, pluginPath, tmpPathDir string + err error + ) + + beforeEach := func(t *testing.T) { + tmpPathDir, err = ioutil.TempDir("", "plugin_list") + assert.Assert(t, err == nil) + + pluginName = "fake-plugin-name" + pluginPath = plugin.CreateTestPluginInPath(t, "kn-"+pluginName, plugin.KnTestPluginScript, plugin.FileModeExecutable, tmpPathDir) + } + + afterEach := func(t *testing.T) { + err = os.RemoveAll(tmpPathDir) + assert.Assert(t, err == nil) + } + + beforeEach(t) + args = []string{pluginPath, pluginName} + setup(t) + defer afterEach(t) + + t.Run("tries to handle args[1:] as plugin and return valid root command", func(t *testing.T) { + checkRootCmd(t, rootCmd) + }) + }) + }) +} - assert.Equal(t, rootCmd.Name(), "kn") - assert.Equal(t, rootCmd.Short, "Knative client") - assert.Assert(t, strings.Contains(rootCmd.Long, "Manage your Knative building blocks:")) +func TestNewKnCommand(t *testing.T) { + var rootCmd *cobra.Command - assert.Assert(t, rootCmd.DisableAutoGenTag) - assert.Assert(t, rootCmd.SilenceUsage) - assert.Assert(t, rootCmd.SilenceErrors) + setup := func(t *testing.T) { + rootCmd = NewKnCommand(commands.KnParams{}) + } - assert.Assert(t, rootCmd.RunE == nil) + t.Run("returns a valid root command", func(t *testing.T) { + setup(t) + checkRootCmd(t, rootCmd) }) t.Run("sets the output params", func(t *testing.T) { + setup(t) assert.Assert(t, rootCmd.OutOrStdout() != nil) }) t.Run("sets the config and kubeconfig global flags", func(t *testing.T) { + setup(t) assert.Assert(t, rootCmd.PersistentFlags().Lookup("config") != nil) assert.Assert(t, rootCmd.PersistentFlags().Lookup("kubeconfig") != nil) }) t.Run("adds the top level commands: version and completion", func(t *testing.T) { + setup(t) checkCommand(t, "version", rootCmd) checkCommand(t, "completion", rootCmd) }) t.Run("adds the top level group commands", func(t *testing.T) { + setup(t) checkCommandGroup(t, "service", rootCmd) checkCommandGroup(t, "revision", rootCmd) }) @@ -69,7 +140,7 @@ func TestNewKnCommand(t *testing.T) { func TestEmptyAndUnknownSubCommands(t *testing.T) { var rootCmd, fakeCmd, fakeSubCmd *cobra.Command - setup := func() { + setup := func(t *testing.T) { rootCmd = NewKnCommand(commands.KnParams{}) fakeCmd = &cobra.Command{ Use: "fake-cmd-name", @@ -84,9 +155,8 @@ func TestEmptyAndUnknownSubCommands(t *testing.T) { assert.Assert(t, fakeSubCmd.RunE == nil) } - setup() - t.Run("deals with empty and unknown sub-commands for all group commands", func(t *testing.T) { + setup(t) EmptyAndUnknownSubCommands(rootCmd) checkCommand(t, "fake-sub-cmd-name", fakeCmd) checkCommandGroup(t, "fake-cmd-name", rootCmd) @@ -95,6 +165,20 @@ func TestEmptyAndUnknownSubCommands(t *testing.T) { // Private +func checkRootCmd(t *testing.T, rootCmd *cobra.Command) { + assert.Assert(t, rootCmd != nil) + + assert.Equal(t, rootCmd.Name(), "kn") + assert.Equal(t, rootCmd.Short, "Knative client") + assert.Assert(t, strings.Contains(rootCmd.Long, "Manage your Knative building blocks:")) + + assert.Assert(t, rootCmd.DisableAutoGenTag) + assert.Assert(t, rootCmd.SilenceUsage) + assert.Assert(t, rootCmd.SilenceErrors) + + assert.Assert(t, rootCmd.RunE == nil) +} + func checkCommand(t *testing.T, name string, rootCmd *cobra.Command) { cmd, _, err := rootCmd.Find([]string{"version"}) assert.Assert(t, err == nil)