diff --git a/cmd/cluster/cluster.go b/cmd/cluster/cluster.go index dc1d65ab4..c514bb9d5 100644 --- a/cmd/cluster/cluster.go +++ b/cmd/cluster/cluster.go @@ -20,16 +20,23 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -// NewClusterCommand returns cobra command object of the airshipctl cluster and adds it's subcommands. +const ( + // TODO: (kkalynovskyi) Add more description when more subcommands are added + clusterLong = ` +This command provides capabilities for interacting with a Kubernetes cluster, +such as getting status and deploying initial infrastructure. +` +) + +// NewClusterCommand creates a command for interacting with a Kubernetes cluster. func NewClusterCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { clusterRootCmd := &cobra.Command{ - Use: "cluster", - // TODO: (kkalynovskyi) Add more description when more subcommands are added - Short: "Control Kubernetes cluster", - Long: "Interactions with Kubernetes cluster, such as get status, deploy initial infrastructure", + Use: "cluster", + Short: "Manage Kubernetes clusters", + Long: clusterLong[1:], } - clusterRootCmd.AddCommand(NewCmdInitInfra(rootSettings)) + clusterRootCmd.AddCommand(NewInitInfraCommand(rootSettings)) return clusterRootCmd } diff --git a/cmd/cluster/cluster_test.go b/cmd/cluster/cluster_test.go index f0e479aea..ccb522ad5 100644 --- a/cmd/cluster/cluster_test.go +++ b/cmd/cluster/cluster_test.go @@ -22,7 +22,7 @@ import ( "opendev.org/airship/airshipctl/testutil" ) -func TestNewClusterCommandReturn(t *testing.T) { +func TestNewClusterCommand(t *testing.T) { fakeRootSettings := &environment.AirshipCTLSettings{ AirshipConfigPath: "../../testdata/k8s/config.yaml", KubeConfigPath: "../../testdata/k8s/kubeconfig.yaml", @@ -31,9 +31,9 @@ func TestNewClusterCommandReturn(t *testing.T) { tests := []*testutil.CmdTest{ { - Name: "cluster-initinfra-cmd-with-defaults", + Name: "cluster-cmd-with-help", CmdLine: "--help", - Cmd: cluster.NewCmdInitInfra(fakeRootSettings), + Cmd: cluster.NewClusterCommand(fakeRootSettings), }, } for _, testcase := range tests { diff --git a/cmd/cluster/initinfra.go b/cmd/cluster/initinfra.go index 45c150294..ee51c1528 100644 --- a/cmd/cluster/initinfra.go +++ b/cmd/cluster/initinfra.go @@ -25,20 +25,24 @@ import ( const ( // TODO add labels in description, when we have them designed - getInitInfraLong = `Deploy initial infrastructure to kubernetes cluster such as ` + - `metal3.io, argo, tiller and other manifest documents with appropriate labels` - getInitInfraExample = `#deploy infra to cluster - airshipctl cluster initinfra` + initInfraLong = ` +Deploy initial infrastructure to kubernetes cluster such as +metal3.io, argo, tiller and other manifest documents with appropriate labels +` + initInfraExample = ` +# Deploy infrastructure to a cluster +airshipctl cluster initinfra +` ) -// NewCmdInitInfra creates a command to deploy initial airship infrastructure -func NewCmdInitInfra(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewInitInfraCommand creates a command to deploy initial airship infrastructure. +func NewInitInfraCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { i := initinfra.NewInfra(rootSettings) initinfraCmd := &cobra.Command{ Use: "initinfra", - Short: "deploy initinfra components to cluster", - Long: getInitInfraLong, - Example: getInitInfraExample, + Short: "Deploy initinfra components to cluster", + Long: initInfraLong[1:], + Example: initInfraExample, RunE: func(cmd *cobra.Command, args []string) error { return i.Run() }, @@ -53,19 +57,19 @@ func addInitinfraFlags(i *initinfra.Infra, cmd *cobra.Command) { &i.DryRun, "dry-run", false, - "Don't deliver documents to the cluster, simulate the changes instead") + "don't deliver documents to the cluster, simulate the changes instead") flags.BoolVar( &i.Prune, "prune", false, - `If set to true, command will delete all kubernetes resources that are not`+ + `if set to true, command will delete all kubernetes resources that are not`+ ` defined in airship documents and have airshipit.org/deployed=initinfra label`) flags.StringVar( &i.ClusterType, "cluster-type", "ephemeral", - `Select cluster type to deploy initial infastructure to;`+ + `select cluster type to deploy initial infrastructure to;`+ ` currently only ephemeral is supported`) } diff --git a/cmd/cluster/initinfra_test.go b/cmd/cluster/initinfra_test.go new file mode 100644 index 000000000..d13371d29 --- /dev/null +++ b/cmd/cluster/initinfra_test.go @@ -0,0 +1,42 @@ +/* + 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 + + https://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 cluster_test + +import ( + "testing" + + "opendev.org/airship/airshipctl/cmd/cluster" + "opendev.org/airship/airshipctl/pkg/environment" + "opendev.org/airship/airshipctl/testutil" +) + +func TestNewInitInfraCommand(t *testing.T) { + fakeRootSettings := &environment.AirshipCTLSettings{ + AirshipConfigPath: "../../testdata/k8s/config.yaml", + KubeConfigPath: "../../testdata/k8s/kubeconfig.yaml", + } + fakeRootSettings.InitConfig() + + tests := []*testutil.CmdTest{ + { + Name: "cluster-initinfra-cmd-with-help", + CmdLine: "--help", + Cmd: cluster.NewInitInfraCommand(fakeRootSettings), + }, + } + for _, testcase := range tests { + testutil.RunTest(t, testcase) + } +} diff --git a/cmd/cluster/testdata/TestNewClusterCommandGoldenOutput/cluster-cmd-with-help.golden b/cmd/cluster/testdata/TestNewClusterCommandGoldenOutput/cluster-cmd-with-help.golden new file mode 100644 index 000000000..8a68ecb62 --- /dev/null +++ b/cmd/cluster/testdata/TestNewClusterCommandGoldenOutput/cluster-cmd-with-help.golden @@ -0,0 +1,14 @@ +This command provides capabilities for interacting with a Kubernetes cluster, +such as getting status and deploying initial infrastructure. + +Usage: + cluster [command] + +Available Commands: + help Help about any command + initinfra Deploy initinfra components to cluster + +Flags: + -h, --help help for cluster + +Use "cluster [command] --help" for more information about a command. diff --git a/cmd/cluster/testdata/TestNewClusterCommandReturnGoldenOutput/cluster-initinfra-cmd-with-defaults.golden b/cmd/cluster/testdata/TestNewClusterCommandReturnGoldenOutput/cluster-initinfra-cmd-with-defaults.golden deleted file mode 100644 index 1577e9cfd..000000000 --- a/cmd/cluster/testdata/TestNewClusterCommandReturnGoldenOutput/cluster-initinfra-cmd-with-defaults.golden +++ /dev/null @@ -1,14 +0,0 @@ -Deploy initial infrastructure to kubernetes cluster such as metal3.io, argo, tiller and other manifest documents with appropriate labels - -Usage: - initinfra [flags] - -Examples: -#deploy infra to cluster - airshipctl cluster initinfra - -Flags: - --cluster-type string Select cluster type to deploy initial infastructure to; currently only ephemeral is supported (default "ephemeral") - --dry-run Don't deliver documents to the cluster, simulate the changes instead - -h, --help help for initinfra - --prune If set to true, command will delete all kubernetes resources that are not defined in airship documents and have airshipit.org/deployed=initinfra label diff --git a/cmd/cluster/testdata/TestNewInitInfraCommandGoldenOutput/cluster-initinfra-cmd-with-help.golden b/cmd/cluster/testdata/TestNewInitInfraCommandGoldenOutput/cluster-initinfra-cmd-with-help.golden new file mode 100644 index 000000000..b084368a9 --- /dev/null +++ b/cmd/cluster/testdata/TestNewInitInfraCommandGoldenOutput/cluster-initinfra-cmd-with-help.golden @@ -0,0 +1,17 @@ +Deploy initial infrastructure to kubernetes cluster such as +metal3.io, argo, tiller and other manifest documents with appropriate labels + +Usage: + initinfra [flags] + +Examples: + +# Deploy infrastructure to a cluster +airshipctl cluster initinfra + + +Flags: + --cluster-type string select cluster type to deploy initial infrastructure to; currently only ephemeral is supported (default "ephemeral") + --dry-run don't deliver documents to the cluster, simulate the changes instead + -h, --help help for initinfra + --prune if set to true, command will delete all kubernetes resources that are not defined in airship documents and have airshipit.org/deployed=initinfra label diff --git a/cmd/completion/completion.go b/cmd/completion/completion.go index 35a88ca10..4e3d88e77 100644 --- a/cmd/completion/completion.go +++ b/cmd/completion/completion.go @@ -21,18 +21,20 @@ import ( "github.com/spf13/cobra" ) -const completionDesc = ` -Generate autocompletion script for airshipctl for the specified shell (bash or zsh). - -This command can generate shell autocompletion. e.g. - - $ airshipctl completion bash - -Can be sourced as such - - $ source <(airshipctl completion bash) +const ( + completionLong = ` +Generate completion script for airshipctl for the specified shell (bash or zsh). ` + completionExample = ` +# Save shell completion to a file +airshipctl completion bash > $HOME/.airship_completions + +# Apply completions to the current shell +source <(airshipctl completion bash) +` +) + var ( completionShells = map[string]func(cmd *cobra.Command) error{ "bash": runCompletionBash, @@ -40,6 +42,7 @@ var ( } ) +// NewCompletionCommand creates a cobra command object for generating shell completion scripts. func NewCompletionCommand() *cobra.Command { shells := make([]string, 0, len(completionShells)) for s := range completionShells { @@ -48,8 +51,9 @@ func NewCompletionCommand() *cobra.Command { cmd := &cobra.Command{ Use: "completion SHELL", - Short: "Generate autocompletions script for the specified shell (bash or zsh)", - Long: completionDesc, + Short: "Generate completion script for the specified shell (bash or zsh)", + Long: completionLong[1:], + Example: completionExample, Args: cobra.ExactArgs(1), RunE: runCompletion, ValidArgs: shells, diff --git a/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-few-args.golden b/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-few-args.golden index 79d8b2e10..4bb1332fe 100644 --- a/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-few-args.golden +++ b/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-few-args.golden @@ -2,6 +2,15 @@ Error: accepts 1 arg(s), received 0 Usage: completion SHELL [flags] +Examples: + +# Save shell completion to a file +airshipctl completion bash > $HOME/.airship_completions + +# Apply completions to the current shell +source <(airshipctl completion bash) + + Flags: -h, --help help for completion diff --git a/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-many-args.golden b/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-many-args.golden index acbc2a9de..986328590 100644 --- a/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-many-args.golden +++ b/cmd/completion/testdata/TestCompletionGoldenOutput/completion-cmd-too-many-args.golden @@ -2,6 +2,15 @@ Error: accepts 1 arg(s), received 2 Usage: completion SHELL [flags] +Examples: + +# Save shell completion to a file +airshipctl completion bash > $HOME/.airship_completions + +# Apply completions to the current shell +source <(airshipctl completion bash) + + Flags: -h, --help help for completion diff --git a/cmd/completion/testdata/TestCompletionGoldenOutput/completion-unknown-shell.golden b/cmd/completion/testdata/TestCompletionGoldenOutput/completion-unknown-shell.golden index f6d6a1635..5f4102bc8 100644 --- a/cmd/completion/testdata/TestCompletionGoldenOutput/completion-unknown-shell.golden +++ b/cmd/completion/testdata/TestCompletionGoldenOutput/completion-unknown-shell.golden @@ -2,6 +2,15 @@ Error: unsupported shell type "fish" Usage: completion SHELL [flags] +Examples: + +# Save shell completion to a file +airshipctl completion bash > $HOME/.airship_completions + +# Apply completions to the current shell +source <(airshipctl completion bash) + + Flags: -h, --help help for completion diff --git a/cmd/config/config.go b/cmd/config/config.go index 56e396b20..3be4b3173 100644 --- a/cmd/config/config.go +++ b/cmd/config/config.go @@ -20,23 +20,21 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -// NewConfigCommand creates a command object for the airshipctl "config" , and adds all child commands to it. +// NewConfigCommand creates a command for interacting with the airshipctl configuration. func NewConfigCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { configRootCmd := &cobra.Command{ Use: "config", DisableFlagsInUseLine: true, - Short: "Modify airshipctl config files", - Long: `Modify airshipctl config files using subcommands -like "airshipctl config set-context my-context" `, + Short: "Manage the airshipctl config file", } - configRootCmd.AddCommand(NewCmdConfigSetCluster(rootSettings)) - configRootCmd.AddCommand(NewCmdConfigGetCluster(rootSettings)) - configRootCmd.AddCommand(NewCmdConfigSetContext(rootSettings)) - configRootCmd.AddCommand(NewCmdConfigGetContext(rootSettings)) - configRootCmd.AddCommand(NewCmdConfigInit(rootSettings)) - configRootCmd.AddCommand(NewCmdConfigSetAuthInfo(rootSettings)) - configRootCmd.AddCommand(NewCmdConfigGetAuthInfo(rootSettings)) - configRootCmd.AddCommand(NewCmdConfigUseContext(rootSettings)) + configRootCmd.AddCommand(NewSetClusterCommand(rootSettings)) + configRootCmd.AddCommand(NewGetClusterCommand(rootSettings)) + configRootCmd.AddCommand(NewSetContextCommand(rootSettings)) + configRootCmd.AddCommand(NewGetContextCommand(rootSettings)) + configRootCmd.AddCommand(NewInitCommand(rootSettings)) + configRootCmd.AddCommand(NewSetAuthInfoCommand(rootSettings)) + configRootCmd.AddCommand(NewGetAuthInfoCommand(rootSettings)) + configRootCmd.AddCommand(NewUseContextCommand(rootSettings)) return configRootCmd } diff --git a/cmd/config/get_authinfo.go b/cmd/config/get_authinfo.go index 419b164bf..80f2a6e5a 100644 --- a/cmd/config/get_authinfo.go +++ b/cmd/config/get_authinfo.go @@ -25,24 +25,29 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var ( - getAuthInfoLong = `Display a specific user's information, or all defined users if no name is provided` +const ( + getAuthInfoLong = ` +Display a specific user's credentials, or all defined user +credentials if no name is provided. +` - getAuthInfoExample = `# List all the users airshipctl knows about + getAuthInfoExample = ` +# List all user credentials airshipctl config get-credentials -# Display a specific user information -airshipctl config get-credentials e2e` +# Display a specific user's credentials +airshipctl config get-credentials exampleUser +` ) -// NewCmdConfigGetAuthInfo returns a Command instance for 'config -AuthInfo' sub command -// An AuthInfo refers to a particular user for a cluster -func NewCmdConfigGetAuthInfo(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewGetAuthInfoCommand creates a command for viewing the user credentials +// defined in the airshipctl config file. +func NewGetAuthInfoCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { o := &config.AuthInfoOptions{} cmd := &cobra.Command{ - Use: "get-credentials NAME", - Short: "Gets a user entry from the airshipctl config", - Long: getAuthInfoLong, + Use: "get-credentials [NAME]", + Short: "Get user credentials from the airshipctl config", + Long: getAuthInfoLong[1:], Example: getAuthInfoExample, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/config/get_authinfo_test.go b/cmd/config/get_authinfo_test.go index 8680a748a..43b927116 100644 --- a/cmd/config/get_authinfo_test.go +++ b/cmd/config/get_authinfo_test.go @@ -47,26 +47,19 @@ func TestGetAuthInfoCmd(t *testing.T) { } cmdTests := []*testutil.CmdTest{ - { - Name: "get-credentials", - CmdLine: fmt.Sprintf("%s", fooAuthInfo), - Cmd: cmd.NewCmdConfigGetAuthInfo(settings), - }, - { - Name: "get-all-credentials", - CmdLine: fmt.Sprintf(""), - Cmd: cmd.NewCmdConfigGetAuthInfo(settings), - }, { Name: "get-specific-credentials", - CmdLine: fmt.Sprintf("%s", fooAuthInfo), - Cmd: cmd.NewCmdConfigGetAuthInfo(settings), + CmdLine: fooAuthInfo, + Cmd: cmd.NewGetAuthInfoCommand(settings), + }, + { + Name: "get-all-credentials", + Cmd: cmd.NewGetAuthInfoCommand(settings), }, - { Name: "missing", - CmdLine: fmt.Sprintf("%s", missingAuthInfo), - Cmd: cmd.NewCmdConfigGetAuthInfo(settings), + CmdLine: missingAuthInfo, + Cmd: cmd.NewGetAuthInfoCommand(settings), Error: fmt.Errorf("user %s information was not "+ "found in the configuration", missingAuthInfo), }, @@ -82,7 +75,7 @@ func TestNoAuthInfosGetAuthInfoCmd(t *testing.T) { cmdTest := &testutil.CmdTest{ Name: "no-credentials", CmdLine: "", - Cmd: cmd.NewCmdConfigGetAuthInfo(settings), + Cmd: cmd.NewGetAuthInfoCommand(settings), } testutil.RunTest(t, cmdTest) } diff --git a/cmd/config/get_cluster.go b/cmd/config/get_cluster.go index ec78c2be5..45d1696c0 100644 --- a/cmd/config/get_cluster.go +++ b/cmd/config/get_cluster.go @@ -25,23 +25,32 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var ( - getClusterLong = "Display a specific cluster or all defined clusters if no name is provided" +const ( + getClusterLong = ` +Display a specific cluster or all defined clusters if no name is provided. - getClusterExample = fmt.Sprintf(` -# List all the clusters airshipctl knows about +Note that if a specific cluster's name is provided, the --cluster-type flag +must also be provided. +Valid values for the --cluster-type flag are [ephemeral|target]. +` + + getClusterExample = ` +# List all clusters airshipctl config get-cluster # Display a specific cluster -airshipctl config get-cluster e2e --%v=ephemeral`, config.FlagClusterType) +airshipctl config get-cluster --cluster-type=ephemeral exampleCluster +` ) -// NewCmdConfigGetCluster returns a Command instance for 'config -Cluster' sub command -func NewCmdConfigGetCluster(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewGetClusterCommand creates a command for viewing the cluster information +// defined in the airshipctl config file. +func NewGetClusterCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { o := &config.ClusterOptions{} cmd := &cobra.Command{ - Use: "get-cluster NAME", - Short: getClusterLong, + Use: "get-cluster [NAME]", + Short: "Get cluster information from the airshipctl config", + Long: getClusterLong[1:], Example: getClusterExample, RunE: func(cmd *cobra.Command, args []string) error { airconfig := rootSettings.Config @@ -80,9 +89,9 @@ func addGetClusterFlags(o *config.ClusterOptions, cmd *cobra.Command) { flags := cmd.Flags() flags.StringVar( &o.ClusterType, - config.FlagClusterType, + "cluster-type", "", - config.FlagClusterType+" for the cluster entry in airshipctl config") + "type of the desired cluster") } func validate(o *config.ClusterOptions) error { diff --git a/cmd/config/get_cluster_test.go b/cmd/config/get_cluster_test.go index 6ae4ae16c..58bc96ef7 100644 --- a/cmd/config/get_cluster_test.go +++ b/cmd/config/get_cluster_test.go @@ -29,8 +29,8 @@ import ( ) const ( - ephemeralFlag = "--" + config.FlagClusterType + "=" + config.Ephemeral - targetFlag = "--" + config.FlagClusterType + "=" + config.Target + ephemeralFlag = "--cluster-type=ephemeral" + targetFlag = "--cluster-type=target" fooCluster = "clusterFoo" barCluster = "clusterBar" @@ -68,12 +68,12 @@ func TestGetClusterCmd(t *testing.T) { { Name: "get-ephemeral", CmdLine: fmt.Sprintf("%s %s", ephemeralFlag, fooCluster), - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), }, { Name: "get-target", CmdLine: fmt.Sprintf("%s %s", targetFlag, fooCluster), - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), }, // FIXME(howell): "airshipctl config get-cluster foo bar" will @@ -84,12 +84,12 @@ func TestGetClusterCmd(t *testing.T) { { Name: "get-multiple-ephemeral", CmdLine: fmt.Sprintf("%s %s %s", ephemeralFlag, fooCluster, barCluster), - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), }, { Name: "get-multiple-target", CmdLine: fmt.Sprintf("%s %s %s", targetFlag, fooCluster, barCluster), - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), }, // FIXME(howell): "airshipctl config get-cluster @@ -98,17 +98,17 @@ func TestGetClusterCmd(t *testing.T) { { Name: "get-all-ephemeral", CmdLine: ephemeralFlag, - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), }, { Name: "get-all-target", CmdLine: targetFlag, - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), }, { Name: "missing", CmdLine: fmt.Sprintf("%s %s", targetFlag, missingCluster), - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), Error: fmt.Errorf("cluster clustermissing information was not " + "found in the configuration"), }, @@ -124,7 +124,7 @@ func TestNoClustersGetClusterCmd(t *testing.T) { cmdTest := &testutil.CmdTest{ Name: "no-clusters", CmdLine: "", - Cmd: cmd.NewCmdConfigGetCluster(settings), + Cmd: cmd.NewGetClusterCommand(settings), } testutil.RunTest(t, cmdTest) } diff --git a/cmd/config/get_context.go b/cmd/config/get_context.go index 71ed41571..b49377b95 100644 --- a/cmd/config/get_context.go +++ b/cmd/config/get_context.go @@ -25,30 +25,31 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var ( - getContextLong = "Display a specific context, the current-context or all defined contexts if no name is provided" +const ( + getContextLong = ` +Display information about contexts such as associated manifests, users, and clusters. +` - getContextExample = fmt.Sprintf(`# List all the contexts airshipctl knows about + getContextExample = ` +# List all contexts airshipctl config get-context # Display the current context -airshipctl config get-context --%v +airshipctl config get-context --current -# Display a specific Context -airshipctl config get-context e2e`, - config.FlagCurrentContext) +# Display a specific context +airshipctl config get-context exampleContext +` ) -// A Context refers to a particular cluster, however it does not specify which of the cluster types -// it relates to. Getting explicit information about a particular context will depend -// on the ClusterType flag. - -// NewCmdConfigGetContext returns a Command instance for 'config -Context' sub command -func NewCmdConfigGetContext(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewGetContextCommand creates a command for viewing cluster information +// defined in the airshipctl config file. +func NewGetContextCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { o := &config.ContextOptions{} cmd := &cobra.Command{ - Use: "get-context NAME", - Short: getContextLong, + Use: "get-context [NAME]", + Short: "Get context information from the airshipctl config", + Long: getContextLong[1:], Example: getContextExample, RunE: func(cmd *cobra.Command, args []string) error { airconfig := rootSettings.Config @@ -88,7 +89,7 @@ func addGetContextFlags(o *config.ContextOptions, cmd *cobra.Command) { flags.BoolVar( &o.CurrentContext, - config.FlagCurrentContext, + "current", false, - "retrieve the current context entry in airshipctl config") + "get the current context") } diff --git a/cmd/config/get_context_test.go b/cmd/config/get_context_test.go index 026565207..17208dd8f 100644 --- a/cmd/config/get_context_test.go +++ b/cmd/config/get_context_test.go @@ -29,8 +29,6 @@ import ( ) const ( - currentContextFlag = "--" + config.FlagCurrentContext - fooContext = "ContextFoo" barContext = "ContextBar" bazContext = "ContextBaz" @@ -53,31 +51,31 @@ func TestGetContextCmd(t *testing.T) { { Name: "get-context", CmdLine: fmt.Sprintf("%s", fooContext), - Cmd: cmd.NewCmdConfigGetContext(settings), + Cmd: cmd.NewGetContextCommand(settings), }, { Name: "get-all-contexts", CmdLine: fmt.Sprintf("%s %s", fooContext, barContext), - Cmd: cmd.NewCmdConfigGetContext(settings), + Cmd: cmd.NewGetContextCommand(settings), }, // This is not implemented yet { Name: "get-multiple-contexts", CmdLine: fmt.Sprintf("%s %s", fooContext, barContext), - Cmd: cmd.NewCmdConfigGetContext(settings), + Cmd: cmd.NewGetContextCommand(settings), }, { Name: "missing", CmdLine: fmt.Sprintf("%s", missingContext), - Cmd: cmd.NewCmdConfigGetContext(settings), + Cmd: cmd.NewGetContextCommand(settings), Error: fmt.Errorf(`Context %s information was not found in the configuration.`, missingContext), }, { Name: "get-current-context", - CmdLine: fmt.Sprintf("%s", currentContextFlag), - Cmd: cmd.NewCmdConfigGetContext(settings), + CmdLine: "--current", + Cmd: cmd.NewGetContextCommand(settings), }, } @@ -91,7 +89,7 @@ func TestNoContextsGetContextCmd(t *testing.T) { cmdTest := &testutil.CmdTest{ Name: "no-contexts", CmdLine: "", - Cmd: cmd.NewCmdConfigGetContext(settings), + Cmd: cmd.NewGetContextCommand(settings), } testutil.RunTest(t, cmdTest) } diff --git a/cmd/config/init.go b/cmd/config/init.go index 93b483625..0a3ec9e8b 100644 --- a/cmd/config/init.go +++ b/cmd/config/init.go @@ -22,19 +22,31 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var ( - configInitLong = "Generate initial configuration files for airshipctl" +const ( + initLong = ` +Generate an airshipctl config file and its associated kubeConfig file. +These files will be written to the $HOME/.airship directory, and will contain +default configurations. + +NOTE: This will overwrite any existing config files in $HOME/.airship +` ) -// NewCmdConfigInit returns a Command instance for 'config init' sub command -func NewCmdConfigInit(rootSettings *environment.AirshipCTLSettings) *cobra.Command { - configInitCmd := &cobra.Command{ +// NewInitCommand creates a command for generating default airshipctl config files. +func NewInitCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { + // TODO(howell): It'd be nice to have a flag to tell + // airshipctl where to store the new files. + // TODO(howell): Currently, this command overwrites whatever the user + // has in their airship directory. We should remove that functionality + // as default and provide and optional --overwrite flag. + cmd := &cobra.Command{ Use: "init", - Short: configInitLong, + Short: "Generate initial configuration files for airshipctl", + Long: initLong[1:], RunE: func(cmd *cobra.Command, args []string) error { return rootSettings.Config.PersistConfig() }, } - return configInitCmd + return cmd } diff --git a/cmd/config/init_test.go b/cmd/config/init_test.go index ca9c919cf..dc5473234 100644 --- a/cmd/config/init_test.go +++ b/cmd/config/init_test.go @@ -27,7 +27,7 @@ func TestConfigInit(t *testing.T) { { Name: "config-init-help", CmdLine: "-h", - Cmd: NewCmdConfigInit(nil), + Cmd: NewInitCommand(nil), }, } diff --git a/cmd/config/set_authinfo.go b/cmd/config/set_authinfo.go index 514692624..0bd5d3d63 100644 --- a/cmd/config/set_authinfo.go +++ b/cmd/config/set_authinfo.go @@ -25,38 +25,43 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var ( - setAuthInfoLong = fmt.Sprintf(`Sets a user entry in airshipctl config -Specifying a name that already exists will merge new fields on top of existing values.`, - ) +const ( + setAuthInfoLong = ` +Create or modify a user credential in the airshipctl config file. - setAuthInfoExample = fmt.Sprintf(` -# Set only the "client-key" field on the "cluster-admin" -# entry, without touching other values: -airshipctl config set-credentials cluster-admin --%v=~/.kube/admin.key +Note that specifying more than one authentication method is an error. +` -# Set basic auth for the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --%v=admin --%v=uXFGweU9l35qcif + setAuthInfoExample = ` +# Create a new user credential with basic auth +airshipctl config set-credentials exampleUser \ + --username=exampleUser \ + --password=examplePassword -# Embed client certificate data in the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --%v=~/.kube/admin.crt --%v=true`, - config.FlagUsername, - config.FlagUsername, - config.FlagPassword, - config.FlagCertFile, - config.FlagEmbedCerts, - ) +# Change the client-key of a user named admin +airshipctl config set-credentials admin \ + --client-key=$HOME/.kube/admin.key + +# Change the username and password of the admin user +airshipctl config set-credentials admin \ + --username=admin \ + --password=uXFGweU9l35qcif + +# Embed client certificate data of the admin user +airshipctl config set-credentials admin \ + --client-certificate=$HOME/.kube/admin.crt \ + --embed-certs +` ) -// NewCmdConfigSetAuthInfo creates a command object for the "set-credentials" action, which -// defines a new AuthInfo airship config. -func NewCmdConfigSetAuthInfo(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewSetAuthInfoCommand creates a command for creating and modifying user +// credentials in the airshipctl config file. +func NewSetAuthInfoCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { o := &config.AuthInfoOptions{} - cmd := &cobra.Command{ Use: "set-credentials NAME", - Short: "Sets a user entry in the airshipctl config", - Long: setAuthInfoLong, + Short: "Manage user credentials", + Long: setAuthInfoLong[1:], Example: setAuthInfoExample, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { @@ -83,37 +88,37 @@ func addSetAuthInfoFlags(o *config.AuthInfoOptions, cmd *cobra.Command) { flags.StringVar( &o.ClientCertificate, - config.FlagCertFile, + "client-certificate", "", - "Path to "+config.FlagCertFile+" file for the user entry in airshipctl") + "path to a certificate") flags.StringVar( &o.ClientKey, - config.FlagKeyFile, + "client-key", "", - "Path to "+config.FlagKeyFile+" file for the user entry in airshipctl") + "path to a key file") flags.StringVar( &o.Token, - config.FlagBearerToken, + "token", "", - config.FlagBearerToken+" for the user entry in airshipctl. Mutually exclusive with username and password flags.") + "token to use for the credential; mutually exclusive with username and password flags.") flags.StringVar( &o.Username, - config.FlagUsername, + "username", "", - config.FlagUsername+" for the user entry in airshipctl. Mutually exclusive with token flag.") + "username for the credential; mutually exclusive with token flag.") flags.StringVar( &o.Password, - config.FlagPassword, + "password", "", - config.FlagPassword+" for the user entry in airshipctl. Mutually exclusive with token flag.") + "password for the credential; mutually exclusive with token flag.") flags.BoolVar( &o.EmbedCertData, - config.FlagEmbedCerts, + "embed-certs", false, - "Embed client cert/key for the user entry in airshipctl") + "if set, embed the client certificate/key into the credential") } diff --git a/cmd/config/set_authinfo_test.go b/cmd/config/set_authinfo_test.go index a1af0421b..27b31facd 100644 --- a/cmd/config/set_authinfo_test.go +++ b/cmd/config/set_authinfo_test.go @@ -52,18 +52,18 @@ func TestConfigSetAuthInfo(t *testing.T) { { Name: "config-cmd-set-authinfo-with-help", CmdLine: "--help", - Cmd: cmd.NewCmdConfigSetAuthInfo(nil), + Cmd: cmd.NewSetAuthInfoCommand(nil), }, { Name: "config-cmd-set-authinfo-too-many-args", CmdLine: "arg1 arg2", - Cmd: cmd.NewCmdConfigSetAuthInfo(nil), + Cmd: cmd.NewSetAuthInfoCommand(nil), Error: fmt.Errorf("accepts %d arg(s), received %d", 1, 2), }, { Name: "config-cmd-set-authinfo-too-few-args", CmdLine: "", - Cmd: cmd.NewCmdConfigSetAuthInfo(nil), + Cmd: cmd.NewSetAuthInfoCommand(nil), Error: fmt.Errorf("accepts %d arg(s), received %d", 1, 0), }, } @@ -89,7 +89,7 @@ func initInputConfig(t *testing.T) (given *config.Config, cleanup func(*testing. func (test setAuthInfoTest) run(t *testing.T) { settings := &environment.AirshipCTLSettings{Config: test.inputConfig} - test.cmdTest.Cmd = cmd.NewCmdConfigSetAuthInfo(settings) + test.cmdTest.Cmd = cmd.NewSetAuthInfoCommand(settings) testutil.RunTest(t, test.cmdTest) afterRunConf := settings.Config @@ -122,8 +122,8 @@ func TestSetAuthInfo(t *testing.T) { { testName: "set-auth-info", flags: []string{ - "--" + config.FlagUsername + "=" + testUsername, - "--" + config.FlagPassword + "=" + testPassword, + "--username=" + testUsername, + "--password=" + testPassword, }, userName: newUserName, userPassword: testPassword, @@ -132,7 +132,7 @@ func TestSetAuthInfo(t *testing.T) { { testName: "modify-auth-info", flags: []string{ - "--" + config.FlagPassword + "=" + testPassword + pwdDelta, + "--password=" + testPassword + pwdDelta, }, userName: existingUserName, userPassword: testPassword + pwdDelta, diff --git a/cmd/config/set_cluster.go b/cmd/config/set_cluster.go index 4799ba374..7b9527eb2 100644 --- a/cmd/config/set_cluster.go +++ b/cmd/config/set_cluster.go @@ -26,42 +26,47 @@ import ( "opendev.org/airship/airshipctl/pkg/log" ) -var ( +const ( setClusterLong = ` -Sets a cluster entry in arshipctl config. -Specifying a name that already exists will merge new fields on top of existing values for those fields.` +Create or modify a cluster in the airshipctl config files. - setClusterExample = fmt.Sprintf(` -# Set only the server field on the e2e cluster entry without touching other values. -airshipctl config set-cluster e2e --%v=ephemeral --%v=https://1.2.3.4 +Since a cluster can be either "ephemeral" or "target", you must specify +cluster-type when managing clusters. +` -# Embed certificate authority data for the e2e cluster entry -airshipctl config set-cluster e2e --%v=target --%v-authority=~/.airship/e2e/kubernetes.ca.crt + setClusterExample = ` +# Set the server field on the ephemeral exampleCluster +airshipctl config set-cluster exampleCluster \ + --cluster-type=ephemeral \ + --server=https://1.2.3.4 -# Disable cert checking for the dev cluster entry -airshipctl config set-cluster e2e --%v=target --%v=true +# Embed certificate authority data for the target exampleCluster +airshipctl config set-cluster exampleCluster \ + --cluster-type=target \ + --client-certificate-authority=$HOME/.airship/ca/kubernetes.ca.crt \ + --embed-certs -# Configure Client Certificate -airshipctl config set-cluster e2e --%v=target --%v=true --%v=".airship/cert_file"`, - config.FlagClusterType, - config.FlagAPIServer, - config.FlagClusterType, - config.FlagCAFile, - config.FlagClusterType, - config.FlagInsecure, - config.FlagClusterType, - config.FlagEmbedCerts, - config.FlagCertFile) +# Disable certificate checking for the target exampleCluster +airshipctl config set-cluster exampleCluster + --cluster-type=target \ + --insecure-skip-tls-verify + +# Configure client certificate for the target exampleCluster +airshipctl config set-cluster exampleCluster \ + --cluster-type=target \ + --embed-certs \ + --client-certificate=$HOME/.airship/cert_file +` ) -// NewCmdConfigSetCluster creates a command object for the "set-cluster" action, which -// defines a new cluster airshipctl config. -func NewCmdConfigSetCluster(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewSetClusterCommand creates a command for creating and modifying clusters +// in the airshipctl config file. +func NewSetClusterCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { o := &config.ClusterOptions{} cmd := &cobra.Command{ Use: "set-cluster NAME", - Short: "Sets a cluster entry in the airshipctl config", - Long: setClusterLong, + Short: "Manage clusters", + Long: setClusterLong[1:], Example: setClusterExample, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { @@ -90,36 +95,36 @@ func addSetClusterFlags(o *config.ClusterOptions, cmd *cobra.Command) { flags.StringVar( &o.Server, - config.FlagAPIServer, + "server", "", - config.FlagAPIServer+" for the cluster entry in airshipctl config") + "server to use for the cluster") flags.StringVar( &o.ClusterType, - config.FlagClusterType, + "cluster-type", "", - config.FlagClusterType+" for the cluster entry in airshipctl config") + "the type of the cluster to add or modify") - err := cmd.MarkFlagRequired(config.FlagClusterType) + err := cmd.MarkFlagRequired("cluster-type") if err != nil { log.Fatal(err) } flags.BoolVar( &o.InsecureSkipTLSVerify, - config.FlagInsecure, + "insecure-skip-tls-verify", true, - config.FlagInsecure+" for the cluster entry in airshipctl config") + "if set, disable certificate checking") flags.StringVar( &o.CertificateAuthority, - config.FlagCAFile, + "certificate-authority", "", - "Path to "+config.FlagCAFile+" file for the cluster entry in airshipctl config") + "path to a certificate authority") flags.BoolVar( &o.EmbedCAData, - config.FlagEmbedCerts, + "embed-certs", false, - config.FlagEmbedCerts+" for the cluster entry in airshipctl config") + "if set, embed the client certificate/key into the cluster") } diff --git a/cmd/config/set_cluster_test.go b/cmd/config/set_cluster_test.go index e574d6d4a..34a61b5e4 100644 --- a/cmd/config/set_cluster_test.go +++ b/cmd/config/set_cluster_test.go @@ -73,10 +73,9 @@ func TestSetClusterWithCAFile(t *testing.T) { givenConfig: given, args: []string{tname}, flags: []string{ - "--" + config.FlagClusterType + "=" + config.Ephemeral, - "--" + config.FlagEmbedCerts + "=false", - "--" + config.FlagCAFile + "=" + certFile, - "--" + config.FlagInsecure + "=false", + "--cluster-type=ephemeral", + "--certificate-authority=" + certFile, + "--insecure-skip-tls-verify=false", }, expectedOutput: fmt.Sprintf("Cluster %q of type %q created.\n", testCluster, config.Ephemeral), expectedConfig: expected, @@ -113,10 +112,10 @@ func TestSetClusterWithCAFileData(t *testing.T) { givenConfig: given, args: []string{tname}, flags: []string{ - "--" + config.FlagClusterType + "=" + config.Ephemeral, - "--" + config.FlagEmbedCerts + "=true", - "--" + config.FlagCAFile + "=" + certFile, - "--" + config.FlagInsecure + "=false", + "--cluster-type=ephemeral", + "--embed-certs", + "--certificate-authority=" + certFile, + "--insecure-skip-tls-verify=false", }, expectedOutput: fmt.Sprintf("Cluster %q of type %q created.\n", tname, config.Ephemeral), expectedConfig: expected, @@ -149,9 +148,8 @@ func TestSetCluster(t *testing.T) { givenConfig: given, args: []string{tname}, flags: []string{ - "--" + config.FlagClusterType + "=" + config.Ephemeral, - "--" + config.FlagAPIServer + "=https://192.168.0.11", - "--" + config.FlagInsecure + "=false", + "--cluster-type=ephemeral", + "--server=https://192.168.0.11", }, expectedOutput: fmt.Sprintf("Cluster %q of type %q created.\n", tname, config.Ephemeral), expectedConfig: expected, @@ -191,8 +189,8 @@ func TestModifyCluster(t *testing.T) { givenConfig: given, args: []string{tname}, flags: []string{ - "--" + config.FlagClusterType + "=" + config.Ephemeral, - "--" + config.FlagAPIServer + "=https://192.168.0.99", + "--cluster-type=ephemeral", + "--server=https://192.168.0.99", }, expectedOutput: fmt.Sprintf("Cluster %q of type %q modified.\n", tname, tctype), expectedConfig: expected, @@ -204,7 +202,7 @@ func (test setClusterTest) run(t *testing.T) { settings := &environment.AirshipCTLSettings{Config: test.givenConfig} buf := bytes.NewBuffer([]byte{}) - cmd := cmd.NewCmdConfigSetCluster(settings) + cmd := cmd.NewSetClusterCommand(settings) cmd.SetOut(buf) cmd.SetArgs(test.args) err := cmd.Flags().Parse(test.flags) @@ -218,7 +216,7 @@ func (test setClusterTest) run(t *testing.T) { // Loads the Config File that was updated afterRunConf := settings.Config // Get ClusterType - tctypeFlag := cmd.Flag(config.FlagClusterType) + tctypeFlag := cmd.Flag("cluster-type") require.NotNil(t, tctypeFlag) tctype := tctypeFlag.Value.String() diff --git a/cmd/config/set_context.go b/cmd/config/set_context.go index 13d6ab7eb..fffbcd99f 100644 --- a/cmd/config/set_context.go +++ b/cmd/config/set_context.go @@ -25,44 +25,40 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var ( +const ( setContextLong = ` -Sets a context entry in arshipctl config. -Specifying a name that already exists will merge new fields on top of existing values for those fields.` +Create or modify a context in the airshipctl config files. +` - setContextExample = fmt.Sprintf(` -# Create a completely new e2e context entry -airshipctl config set-context e2e --%v=kube-system --%v=manifest --%v=auth-info --%v=%v + setContextExample = ` +# Create a new context named "exampleContext" +airshipctl config set-context exampleContext \ + --namespace=kube-system \ + --manifest=exampleManifest \ + --user=exampleUser + --cluster-type=target -# Update the current-context to e2e -airshipctl config set-context e2e - -# Update attributes of the current-context -airshipctl config set-context --%s --%v=manifest`, - config.FlagNamespace, - config.FlagManifest, - config.FlagAuthInfoName, - config.FlagClusterType, - config.Target, - config.FlagCurrent, - config.FlagManifest) +# Update the manifest of the current-context +airshipctl config set-context \ + --current \ + --manifest=exampleManifest +` ) -// NewCmdConfigSetContext creates a command object for the "set-context" action, which -// creates and modifies contexts in the airshipctl config -func NewCmdConfigSetContext(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewSetContextCommand creates a command for creating and modifying contexts +// in the airshipctl config +func NewSetContextCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { o := &config.ContextOptions{} - cmd := &cobra.Command{ Use: "set-context NAME", - Short: "Switch to a new context or update context values in the airshipctl config", - Long: setContextLong, + Short: "Manage contexts", + Long: setContextLong[1:], Example: setContextExample, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { nFlags := cmd.Flags().NFlag() if len(args) == 1 { - //context name is made optional with --current flag added + // context name is made optional with --current flag added o.Name = args[0] } if o.Name != "" && nFlags == 0 { @@ -93,37 +89,37 @@ func addSetContextFlags(o *config.ContextOptions, cmd *cobra.Command) { flags.StringVar( &o.Cluster, - config.FlagClusterName, + "cluster", "", - "sets the "+config.FlagClusterName+" for the specified context in the airshipctl config") + "set the cluster for the specified context") flags.StringVar( &o.AuthInfo, - config.FlagAuthInfoName, + "user", "", - "sets the "+config.FlagAuthInfoName+" for the specified context in the airshipctl config") + "set the user for the specified context") flags.StringVar( &o.Manifest, - config.FlagManifest, + "manifest", "", - "sets the "+config.FlagManifest+" for the specified context in the airshipctl config") + "set the manifest for the specified context") flags.StringVar( &o.Namespace, - config.FlagNamespace, + "namespace", "", - "sets the "+config.FlagNamespace+" for the specified context in the airshipctl config") + "set the namespace for the specified context") flags.StringVar( &o.ClusterType, - config.FlagClusterType, + "cluster-type", "", - "sets the "+config.FlagClusterType+" for the specified context in the airshipctl config") + "set the cluster-type for the specified context") flags.BoolVar( &o.Current, - config.FlagCurrent, + "current", false, - "use current context from airshipctl config") + "update the current context") } diff --git a/cmd/config/set_context_test.go b/cmd/config/set_context_test.go index f5c2b7f8f..1cab47445 100644 --- a/cmd/config/set_context_test.go +++ b/cmd/config/set_context_test.go @@ -49,17 +49,17 @@ func TestConfigSetContext(t *testing.T) { { Name: "config-cmd-set-context-with-help", CmdLine: "--help", - Cmd: cmd.NewCmdConfigSetContext(nil), + Cmd: cmd.NewSetContextCommand(nil), }, { Name: "config-cmd-set-context-no-flags", CmdLine: "context", - Cmd: cmd.NewCmdConfigSetContext(nil), + Cmd: cmd.NewSetContextCommand(nil), }, { Name: "config-cmd-set-context-too-many-args", CmdLine: "arg1 arg2", - Cmd: cmd.NewCmdConfigSetContext(nil), + Cmd: cmd.NewSetContextCommand(nil), Error: fmt.Errorf("accepts at most %d arg(s), received %d", 1, 2), }, } @@ -84,10 +84,10 @@ func TestSetContext(t *testing.T) { testName: "set-context", contextName: "dummycontext", flags: []string{ - "--" + config.FlagClusterType + "=" + config.Target, - "--" + config.FlagAuthInfoName + "=" + testUser, - "--" + config.FlagManifest + "=" + defaultManifest, - "--" + config.FlagNamespace + "=" + defaultNamespace, + "--cluster-type=target", + "--user=" + testUser, + "--manifest=" + defaultManifest, + "--namespace=" + defaultNamespace, }, givenConfig: given, manifest: defaultManifest, @@ -102,7 +102,7 @@ func TestSetContext(t *testing.T) { testName: "modify-context", contextName: "def_target", flags: []string{ - "--" + config.FlagManifest + "=" + testManifest, + "--manifest=" + testManifest, }, givenConfig: given, manifest: testManifest, @@ -129,7 +129,7 @@ func (test setContextTest) run(t *testing.T) { // Get the Environment settings := &environment.AirshipCTLSettings{Config: test.givenConfig} - test.cmdTest.Cmd = cmd.NewCmdConfigSetContext(settings) + test.cmdTest.Cmd = cmd.NewSetContextCommand(settings) testutil.RunTest(t, test.cmdTest) afterRunConf := settings.Config diff --git a/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden b/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden index 4d8e91389..84d41a2d5 100644 --- a/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden +++ b/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden @@ -1,19 +1,18 @@ -Modify airshipctl config files using subcommands -like "airshipctl config set-context my-context" +Manage the airshipctl config file Usage: config [command] Available Commands: - get-cluster Display a specific cluster or all defined clusters if no name is provided - get-context Display a specific context, the current-context or all defined contexts if no name is provided - get-credentials Gets a user entry from the airshipctl config + get-cluster Get cluster information from the airshipctl config + get-context Get context information from the airshipctl config + get-credentials Get user credentials from the airshipctl config help Help about any command init Generate initial configuration files for airshipctl - set-cluster Sets a cluster entry in the airshipctl config - set-context Switch to a new context or update context values in the airshipctl config - set-credentials Sets a user entry in the airshipctl config - use-context Switch to a different airshipctl context. + set-cluster Manage clusters + set-context Manage contexts + set-credentials Manage user credentials + use-context Switch to a different context Flags: -h, --help help for config diff --git a/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden b/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden index 6303793da..fcc51693f 100644 --- a/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden +++ b/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden @@ -1,4 +1,8 @@ -Generate initial configuration files for airshipctl +Generate an airshipctl config file and its associated kubeConfig file. +These files will be written to the $HOME/.airship directory, and will contain +default configurations. + +NOTE: This will overwrite any existing config files in $HOME/.airship Usage: init [flags] diff --git a/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-few-args.golden b/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-few-args.golden index 998a62aa5..37bbcd501 100644 --- a/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-few-args.golden +++ b/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-few-args.golden @@ -4,22 +4,32 @@ Usage: Examples: -# Set only the "client-key" field on the "cluster-admin" -# entry, without touching other values: -airshipctl config set-credentials cluster-admin --username=~/.kube/admin.key +# Create a new user credential with basic auth +airshipctl config set-credentials exampleUser \ + --username=exampleUser \ + --password=examplePassword -# Set basic auth for the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --username=admin --password=uXFGweU9l35qcif +# Change the client-key of a user named admin +airshipctl config set-credentials admin \ + --client-key=$HOME/.kube/admin.key + +# Change the username and password of the admin user +airshipctl config set-credentials admin \ + --username=admin \ + --password=uXFGweU9l35qcif + +# Embed client certificate data of the admin user +airshipctl config set-credentials admin \ + --client-certificate=$HOME/.kube/admin.crt \ + --embed-certs -# Embed client certificate data in the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true Flags: - --client-certificate string Path to client-certificate file for the user entry in airshipctl - --client-key string Path to client-key file for the user entry in airshipctl - --embed-certs Embed client cert/key for the user entry in airshipctl + --client-certificate string path to a certificate + --client-key string path to a key file + --embed-certs if set, embed the client certificate/key into the credential -h, --help help for set-credentials - --password string password for the user entry in airshipctl. Mutually exclusive with token flag. - --token string token for the user entry in airshipctl. Mutually exclusive with username and password flags. - --username string username for the user entry in airshipctl. Mutually exclusive with token flag. + --password string password for the credential; mutually exclusive with token flag. + --token string token to use for the credential; mutually exclusive with username and password flags. + --username string username for the credential; mutually exclusive with token flag. diff --git a/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-many-args.golden b/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-many-args.golden index d35fefb10..ffb7397d4 100644 --- a/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-many-args.golden +++ b/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-too-many-args.golden @@ -4,22 +4,32 @@ Usage: Examples: -# Set only the "client-key" field on the "cluster-admin" -# entry, without touching other values: -airshipctl config set-credentials cluster-admin --username=~/.kube/admin.key +# Create a new user credential with basic auth +airshipctl config set-credentials exampleUser \ + --username=exampleUser \ + --password=examplePassword -# Set basic auth for the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --username=admin --password=uXFGweU9l35qcif +# Change the client-key of a user named admin +airshipctl config set-credentials admin \ + --client-key=$HOME/.kube/admin.key + +# Change the username and password of the admin user +airshipctl config set-credentials admin \ + --username=admin \ + --password=uXFGweU9l35qcif + +# Embed client certificate data of the admin user +airshipctl config set-credentials admin \ + --client-certificate=$HOME/.kube/admin.crt \ + --embed-certs -# Embed client certificate data in the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true Flags: - --client-certificate string Path to client-certificate file for the user entry in airshipctl - --client-key string Path to client-key file for the user entry in airshipctl - --embed-certs Embed client cert/key for the user entry in airshipctl + --client-certificate string path to a certificate + --client-key string path to a key file + --embed-certs if set, embed the client certificate/key into the credential -h, --help help for set-credentials - --password string password for the user entry in airshipctl. Mutually exclusive with token flag. - --token string token for the user entry in airshipctl. Mutually exclusive with username and password flags. - --username string username for the user entry in airshipctl. Mutually exclusive with token flag. + --password string password for the credential; mutually exclusive with token flag. + --token string token to use for the credential; mutually exclusive with username and password flags. + --username string username for the credential; mutually exclusive with token flag. diff --git a/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-with-help.golden b/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-with-help.golden index dfa8a5623..94c0fff27 100644 --- a/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-with-help.golden +++ b/cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-with-help.golden @@ -1,26 +1,37 @@ -Sets a user entry in airshipctl config -Specifying a name that already exists will merge new fields on top of existing values. +Create or modify a user credential in the airshipctl config file. + +Note that specifying more than one authentication method is an error. Usage: set-credentials NAME [flags] Examples: -# Set only the "client-key" field on the "cluster-admin" -# entry, without touching other values: -airshipctl config set-credentials cluster-admin --username=~/.kube/admin.key +# Create a new user credential with basic auth +airshipctl config set-credentials exampleUser \ + --username=exampleUser \ + --password=examplePassword -# Set basic auth for the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --username=admin --password=uXFGweU9l35qcif +# Change the client-key of a user named admin +airshipctl config set-credentials admin \ + --client-key=$HOME/.kube/admin.key + +# Change the username and password of the admin user +airshipctl config set-credentials admin \ + --username=admin \ + --password=uXFGweU9l35qcif + +# Embed client certificate data of the admin user +airshipctl config set-credentials admin \ + --client-certificate=$HOME/.kube/admin.crt \ + --embed-certs -# Embed client certificate data in the "cluster-admin" entry -airshipctl config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true Flags: - --client-certificate string Path to client-certificate file for the user entry in airshipctl - --client-key string Path to client-key file for the user entry in airshipctl - --embed-certs Embed client cert/key for the user entry in airshipctl + --client-certificate string path to a certificate + --client-key string path to a key file + --embed-certs if set, embed the client certificate/key into the credential -h, --help help for set-credentials - --password string password for the user entry in airshipctl. Mutually exclusive with token flag. - --token string token for the user entry in airshipctl. Mutually exclusive with username and password flags. - --username string username for the user entry in airshipctl. Mutually exclusive with token flag. + --password string password for the credential; mutually exclusive with token flag. + --token string token to use for the credential; mutually exclusive with username and password flags. + --username string username for the credential; mutually exclusive with token flag. diff --git a/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-too-many-args.golden b/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-too-many-args.golden index 266cd938b..e1ca03cc8 100644 --- a/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-too-many-args.golden +++ b/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-too-many-args.golden @@ -4,21 +4,25 @@ Usage: Examples: -# Create a completely new e2e context entry -airshipctl config set-context e2e --namespace=kube-system --manifest=manifest --user=auth-info --cluster-type=target +# Create a new context named "exampleContext" +airshipctl config set-context exampleContext \ + --namespace=kube-system \ + --manifest=exampleManifest \ + --user=exampleUser + --cluster-type=target -# Update the current-context to e2e -airshipctl config set-context e2e +# Update the manifest of the current-context +airshipctl config set-context \ + --current \ + --manifest=exampleManifest -# Update attributes of the current-context -airshipctl config set-context --current --manifest=manifest Flags: - --cluster string sets the cluster for the specified context in the airshipctl config - --cluster-type string sets the cluster-type for the specified context in the airshipctl config - --current use current context from airshipctl config + --cluster string set the cluster for the specified context + --cluster-type string set the cluster-type for the specified context + --current update the current context -h, --help help for set-context - --manifest string sets the manifest for the specified context in the airshipctl config - --namespace string sets the namespace for the specified context in the airshipctl config - --user string sets the user for the specified context in the airshipctl config + --manifest string set the manifest for the specified context + --namespace string set the namespace for the specified context + --user string set the user for the specified context diff --git a/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-with-help.golden b/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-with-help.golden index d7fd0c3f8..d7123f097 100644 --- a/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-with-help.golden +++ b/cmd/config/testdata/TestConfigSetContextGoldenOutput/config-cmd-set-context-with-help.golden @@ -1,26 +1,28 @@ - -Sets a context entry in arshipctl config. -Specifying a name that already exists will merge new fields on top of existing values for those fields. +Create or modify a context in the airshipctl config files. Usage: set-context NAME [flags] Examples: -# Create a completely new e2e context entry -airshipctl config set-context e2e --namespace=kube-system --manifest=manifest --user=auth-info --cluster-type=target +# Create a new context named "exampleContext" +airshipctl config set-context exampleContext \ + --namespace=kube-system \ + --manifest=exampleManifest \ + --user=exampleUser + --cluster-type=target -# Update the current-context to e2e -airshipctl config set-context e2e +# Update the manifest of the current-context +airshipctl config set-context \ + --current \ + --manifest=exampleManifest -# Update attributes of the current-context -airshipctl config set-context --current --manifest=manifest Flags: - --cluster string sets the cluster for the specified context in the airshipctl config - --cluster-type string sets the cluster-type for the specified context in the airshipctl config - --current use current context from airshipctl config + --cluster string set the cluster for the specified context + --cluster-type string set the cluster-type for the specified context + --current update the current context -h, --help help for set-context - --manifest string sets the manifest for the specified context in the airshipctl config - --namespace string sets the namespace for the specified context in the airshipctl config - --user string sets the user for the specified context in the airshipctl config + --manifest string set the manifest for the specified context + --namespace string set the namespace for the specified context + --user string set the user for the specified context diff --git a/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-does-not-exist.golden b/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-does-not-exist.golden index 6c33a616d..912efafb7 100644 --- a/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-does-not-exist.golden +++ b/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-does-not-exist.golden @@ -4,8 +4,9 @@ Usage: Examples: -# Switch to a context named "e2e" -airshipctl config use-context e2e +# Switch to a context named "exampleContext" +airshipctl config use-context exampleContext + Flags: -h, --help help for use-context diff --git a/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-no-args.golden b/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-no-args.golden index 0b38331b6..fd8e67f0e 100644 --- a/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-no-args.golden +++ b/cmd/config/testdata/TestConfigUseContextGoldenOutput/config-use-context-no-args.golden @@ -4,8 +4,9 @@ Usage: Examples: -# Switch to a context named "e2e" -airshipctl config use-context e2e +# Switch to a context named "exampleContext" +airshipctl config use-context exampleContext + Flags: -h, --help help for use-context diff --git a/cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-credentials.golden b/cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-credentials.golden deleted file mode 100644 index c85b2eab1..000000000 --- a/cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-credentials.golden +++ /dev/null @@ -1,7 +0,0 @@ -LocationOfOrigin: "" -client-certificate: dummy_certificate -client-key: dummy_key -password: dummy_password -token: dummy_token -username: dummy_user - diff --git a/cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/missing.golden b/cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/missing.golden index d906e8dd3..252b86b55 100644 --- a/cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/missing.golden +++ b/cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/missing.golden @@ -1,13 +1,15 @@ Error: Missing configuration: User credentials with name 'authinfoMissing' Usage: - get-credentials NAME [flags] + get-credentials [NAME] [flags] Examples: -# List all the users airshipctl knows about + +# List all user credentials airshipctl config get-credentials -# Display a specific user information -airshipctl config get-credentials e2e +# Display a specific user's credentials +airshipctl config get-credentials exampleUser + Flags: -h, --help help for get-credentials diff --git a/cmd/config/testdata/TestGetClusterCmdGoldenOutput/missing.golden b/cmd/config/testdata/TestGetClusterCmdGoldenOutput/missing.golden index 9a3253af2..a84b46faf 100644 --- a/cmd/config/testdata/TestGetClusterCmdGoldenOutput/missing.golden +++ b/cmd/config/testdata/TestGetClusterCmdGoldenOutput/missing.golden @@ -1,16 +1,17 @@ Error: Missing configuration: Cluster with name 'clusterMissing' of type 'target' Usage: - get-cluster NAME [flags] + get-cluster [NAME] [flags] Examples: -# List all the clusters airshipctl knows about +# List all clusters airshipctl config get-cluster # Display a specific cluster -airshipctl config get-cluster e2e --cluster-type=ephemeral +airshipctl config get-cluster --cluster-type=ephemeral exampleCluster + Flags: - --cluster-type string cluster-type for the cluster entry in airshipctl config + --cluster-type string type of the desired cluster -h, --help help for get-cluster diff --git a/cmd/config/testdata/TestGetContextCmdGoldenOutput/missing.golden b/cmd/config/testdata/TestGetContextCmdGoldenOutput/missing.golden index 694d3aa8d..fc4ccbd77 100644 --- a/cmd/config/testdata/TestGetContextCmdGoldenOutput/missing.golden +++ b/cmd/config/testdata/TestGetContextCmdGoldenOutput/missing.golden @@ -1,18 +1,20 @@ Error: Missing configuration: Context with name 'contextMissing' Usage: - get-context NAME [flags] + get-context [NAME] [flags] Examples: -# List all the contexts airshipctl knows about + +# List all contexts airshipctl config get-context # Display the current context -airshipctl config get-context --current-context +airshipctl config get-context --current + +# Display a specific context +airshipctl config get-context exampleContext -# Display a specific Context -airshipctl config get-context e2e Flags: - --current-context retrieve the current context entry in airshipctl config - -h, --help help for get-context + --current get the current context + -h, --help help for get-context diff --git a/cmd/config/use_context.go b/cmd/config/use_context.go index 748505bdc..9d1816473 100644 --- a/cmd/config/use_context.go +++ b/cmd/config/use_context.go @@ -25,21 +25,23 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var ( - useContextLong = "Switch to a new context defined in the airshipctl config file." +const ( + useContextLong = ` +Switch to a different context defined in the airshipctl config file. +` useContextExample = ` -# Switch to a context named "e2e" -airshipctl config use-context e2e` +# Switch to a context named "exampleContext" +airshipctl config use-context exampleContext +` ) -// NewCmdConfigUseContext creates a command object for the "use-context" action, which -// switches to a defined airshipctl context. -func NewCmdConfigUseContext(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewUseContextCommand creates a command for switching to a defined airshipctl context. +func NewUseContextCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { cmd := &cobra.Command{ Use: "use-context NAME", - Short: "Switch to a different airshipctl context.", - Long: useContextLong, + Short: "Switch to a different context", + Long: useContextLong[1:], Example: useContextExample, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/config/use_context_test.go b/cmd/config/use_context_test.go index 186c52106..7929f18f3 100644 --- a/cmd/config/use_context_test.go +++ b/cmd/config/use_context_test.go @@ -31,18 +31,18 @@ func TestConfigUseContext(t *testing.T) { { Name: "config-use-context", CmdLine: "dummy_context", - Cmd: cmd.NewCmdConfigUseContext(settings), + Cmd: cmd.NewUseContextCommand(settings), }, { Name: "config-use-context-no-args", CmdLine: "", - Cmd: cmd.NewCmdConfigUseContext(settings), + Cmd: cmd.NewUseContextCommand(settings), Error: errors.New("accepts 1 arg(s), received 0"), }, { Name: "config-use-context-does-not-exist", CmdLine: "foo", - Cmd: cmd.NewCmdConfigUseContext(settings), + Cmd: cmd.NewUseContextCommand(settings), Error: errors.New("missing configuration: context with name 'foo'"), }, } diff --git a/cmd/document/document.go b/cmd/document/document.go index 3a17dc39d..c151b0631 100644 --- a/cmd/document/document.go +++ b/cmd/document/document.go @@ -24,12 +24,12 @@ import ( func NewDocumentCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { documentRootCmd := &cobra.Command{ Use: "document", - Short: "manages deployment documents", + Short: "Manage deployment documents", } - documentRootCmd.AddCommand(NewDocumentPullCommand(rootSettings)) + documentRootCmd.AddCommand(NewPullCommand(rootSettings)) documentRootCmd.AddCommand(NewRenderCommand(rootSettings)) - documentRootCmd.AddCommand(NewDocumentPluginCommand(rootSettings)) + documentRootCmd.AddCommand(NewPluginCommand(rootSettings)) return documentRootCmd } diff --git a/cmd/document/plugin.go b/cmd/document/plugin.go index aa6de28d1..23d3d2886 100644 --- a/cmd/document/plugin.go +++ b/cmd/document/plugin.go @@ -23,14 +23,22 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -var longDescription = `Subcommand reads configuration file CONFIG passed as -a first argument and determines a particular plugin to execute. Additional -arguments may be passed to this sub-command abd can be used by the -particular plugin. CONFIG file must be structured as kubernetes -manifest (i.e. resource) and must have 'apiVersion' and 'kind' keys. +const ( + pluginLong = ` +This command is meant to be used as a kustomize exec plugin. -Example: -$ cat /tmp/generator.yaml +The command reads the configuration file CONFIG passed as a first argument and +determines a particular plugin to execute. Additional arguments may be passed +to this command and can be used by the particular plugin. + +CONFIG must be a structured kubernetes manifest (i.e. resource) and must have +'apiVersion' and 'kind' keys. If the appropriate plugin was not found, the +command returns an error. +` + + pluginExample = ` +# Perform a replacement on a deployment. Prior to running this command, +# the file '/tmp/replacement.yaml' should be created as follows: --- apiVersion: airshipit.org/v1alpha1 kind: ReplacementTransformer @@ -45,21 +53,20 @@ replacements: fieldrefs: - spec.template.spec.containers[name=nginx-latest].image -$ airshipctl document plugin /tmp/generator.yaml - -subcommand will try to identify appropriate plugin using apiVersion and -kind keys (a.k.a group, version, kind) as an identifier. If appropriate -plugin was not found command returns an error. +# The replacement can then be performed. Output defaults to stdout. +airshipctl document plugin /tmp/replacement.yaml ` +) -// NewDocumentPluginCommand creates a new command which can act as kustomize +// NewPluginCommand creates a new command which can act as kustomize // exec plugin. -func NewDocumentPluginCommand(rootSetting *environment.AirshipCTLSettings) *cobra.Command { +func NewPluginCommand(rootSetting *environment.AirshipCTLSettings) *cobra.Command { pluginCmd := &cobra.Command{ - Use: "plugin CONFIG [ARGS]", - Short: "used as kustomize exec plugin", - Long: longDescription, - Args: cobra.MinimumNArgs(1), + Use: "plugin CONFIG [ARGS]", + Short: "Run as a kustomize exec plugin", + Long: pluginLong[1:], + Example: pluginExample, + Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { cfg, err := ioutil.ReadFile(args[0]) if err != nil { diff --git a/cmd/document/plugin_test.go b/cmd/document/plugin_test.go index ee7f9502e..7974d0cb7 100644 --- a/cmd/document/plugin_test.go +++ b/cmd/document/plugin_test.go @@ -26,19 +26,19 @@ func TestPlugin(t *testing.T) { { Name: "document-plugin-cmd-with-help", CmdLine: "--help", - Cmd: NewDocumentPluginCommand(nil), + Cmd: NewPluginCommand(nil), }, { Name: "document-plugin-cmd-with-empty-args", CmdLine: "", Error: fmt.Errorf("requires at least 1 arg(s), only received 0"), - Cmd: NewDocumentPluginCommand(nil), + Cmd: NewPluginCommand(nil), }, { Name: "document-plugin-cmd-with-nonexistent-config", CmdLine: "/some/random/path.yaml", Error: fmt.Errorf("open /some/random/path.yaml: no such file or directory"), - Cmd: NewDocumentPluginCommand(nil), + Cmd: NewPluginCommand(nil), }, } diff --git a/cmd/document/pull.go b/cmd/document/pull.go index 604f45cba..a14712d26 100644 --- a/cmd/document/pull.go +++ b/cmd/document/pull.go @@ -21,12 +21,12 @@ import ( "opendev.org/airship/airshipctl/pkg/environment" ) -// NewDocumentPullCommand creates a new command for pulling airship document repositories -func NewDocumentPullCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { +// NewPullCommand creates a new command for pulling airship document repositories +func NewPullCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { settings := pull.Settings{AirshipCTLSettings: rootSettings} documentPullCmd := &cobra.Command{ Use: "pull", - Short: "pulls documents from remote git repository", + Short: "Pulls documents from remote git repository", RunE: func(cmd *cobra.Command, args []string) error { return settings.Pull() }, diff --git a/cmd/document/pull_test.go b/cmd/document/pull_test.go index 6753610e1..b02e0bfaf 100644 --- a/cmd/document/pull_test.go +++ b/cmd/document/pull_test.go @@ -50,12 +50,12 @@ func TestPull(t *testing.T) { { Name: "document-pull-cmd-with-defaults", CmdLine: "", - Cmd: NewDocumentPullCommand(getDummyAirshipSettings()), + Cmd: NewPullCommand(getDummyAirshipSettings()), }, { Name: "document-pull-cmd-with-help", CmdLine: "--help", - Cmd: NewDocumentPullCommand(nil), + Cmd: NewPullCommand(nil), }, } diff --git a/cmd/document/render.go b/cmd/document/render.go index ce59c9943..7db291e65 100644 --- a/cmd/document/render.go +++ b/cmd/document/render.go @@ -46,33 +46,33 @@ func addRenderFlags(settings *render.Settings, cmd *cobra.Command) { "label", "l", nil, - "Filter documents by Labels") + "filter documents by Labels") flags.StringArrayVarP( &settings.Annotation, "annotation", "a", nil, - "Filter documents by Annotations") + "filter documents by Annotations") flags.StringArrayVarP( &settings.GroupVersion, "apiversion", "g", nil, - "Filter documents by API version") + "filter documents by API version") flags.StringArrayVarP( &settings.Kind, "kind", "k", nil, - "Filter documents by Kinds") + "filter documents by Kinds") flags.StringVarP( &settings.RawFilter, "filter", "f", "", - "Logical expression for document filtering") + "logical expression for document filtering") } diff --git a/cmd/document/testdata/TestDocumentGoldenOutput/document-render-with-help.golden b/cmd/document/testdata/TestDocumentGoldenOutput/document-render-with-help.golden index a00aa24a1..aea59a5b8 100644 --- a/cmd/document/testdata/TestDocumentGoldenOutput/document-render-with-help.golden +++ b/cmd/document/testdata/TestDocumentGoldenOutput/document-render-with-help.golden @@ -4,9 +4,9 @@ Usage: render [flags] Flags: - -a, --annotation stringArray Filter documents by Annotations - -g, --apiversion stringArray Filter documents by API version - -f, --filter string Logical expression for document filtering + -a, --annotation stringArray filter documents by Annotations + -g, --apiversion stringArray filter documents by API version + -f, --filter string logical expression for document filtering -h, --help help for render - -k, --kind stringArray Filter documents by Kinds - -l, --label stringArray Filter documents by Labels + -k, --kind stringArray filter documents by Kinds + -l, --label stringArray filter documents by Labels diff --git a/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-empty-args.golden b/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-empty-args.golden index 8e125e5c7..e936b1f9c 100644 --- a/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-empty-args.golden +++ b/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-empty-args.golden @@ -2,6 +2,28 @@ Error: requires at least 1 arg(s), only received 0 Usage: plugin CONFIG [ARGS] [flags] +Examples: + +# Perform a replacement on a deployment. Prior to running this command, +# the file '/tmp/replacement.yaml' should be created as follows: +--- +apiVersion: airshipit.org/v1alpha1 +kind: ReplacementTransformer +metadata: + name: notImportantHere +replacements: +- source: + value: nginx:newtag + target: + objref: + kind: Deployment + fieldrefs: + - spec.template.spec.containers[name=nginx-latest].image + +# The replacement can then be performed. Output defaults to stdout. +airshipctl document plugin /tmp/replacement.yaml + + Flags: -h, --help help for plugin diff --git a/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-help.golden b/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-help.golden index 3e90219e8..b10d1154b 100644 --- a/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-help.golden +++ b/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-help.golden @@ -1,11 +1,20 @@ -Subcommand reads configuration file CONFIG passed as -a first argument and determines a particular plugin to execute. Additional -arguments may be passed to this sub-command abd can be used by the -particular plugin. CONFIG file must be structured as kubernetes -manifest (i.e. resource) and must have 'apiVersion' and 'kind' keys. +This command is meant to be used as a kustomize exec plugin. -Example: -$ cat /tmp/generator.yaml +The command reads the configuration file CONFIG passed as a first argument and +determines a particular plugin to execute. Additional arguments may be passed +to this command and can be used by the particular plugin. + +CONFIG must be a structured kubernetes manifest (i.e. resource) and must have +'apiVersion' and 'kind' keys. If the appropriate plugin was not found, the +command returns an error. + +Usage: + plugin CONFIG [ARGS] [flags] + +Examples: + +# Perform a replacement on a deployment. Prior to running this command, +# the file '/tmp/replacement.yaml' should be created as follows: --- apiVersion: airshipit.org/v1alpha1 kind: ReplacementTransformer @@ -20,14 +29,9 @@ replacements: fieldrefs: - spec.template.spec.containers[name=nginx-latest].image -$ airshipctl document plugin /tmp/generator.yaml +# The replacement can then be performed. Output defaults to stdout. +airshipctl document plugin /tmp/replacement.yaml -subcommand will try to identify appropriate plugin using apiVersion and -kind keys (a.k.a group, version, kind) as an identifier. If appropriate -plugin was not found command returns an error. - -Usage: - plugin CONFIG [ARGS] [flags] Flags: -h, --help help for plugin diff --git a/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-nonexistent-config.golden b/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-nonexistent-config.golden index 6c1fedf43..dd229178d 100644 --- a/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-nonexistent-config.golden +++ b/cmd/document/testdata/TestPluginGoldenOutput/document-plugin-cmd-with-nonexistent-config.golden @@ -2,6 +2,28 @@ Error: open /some/random/path.yaml: no such file or directory Usage: plugin CONFIG [ARGS] [flags] +Examples: + +# Perform a replacement on a deployment. Prior to running this command, +# the file '/tmp/replacement.yaml' should be created as follows: +--- +apiVersion: airshipit.org/v1alpha1 +kind: ReplacementTransformer +metadata: + name: notImportantHere +replacements: +- source: + value: nginx:newtag + target: + objref: + kind: Deployment + fieldrefs: + - spec.template.spec.containers[name=nginx-latest].image + +# The replacement can then be performed. Output defaults to stdout. +airshipctl document plugin /tmp/replacement.yaml + + Flags: -h, --help help for plugin diff --git a/cmd/document/testdata/TestPullGoldenOutput/document-pull-cmd-with-help.golden b/cmd/document/testdata/TestPullGoldenOutput/document-pull-cmd-with-help.golden index efb4d2b57..b618d9ded 100644 --- a/cmd/document/testdata/TestPullGoldenOutput/document-pull-cmd-with-help.golden +++ b/cmd/document/testdata/TestPullGoldenOutput/document-pull-cmd-with-help.golden @@ -1,4 +1,4 @@ -pulls documents from remote git repository +Pulls documents from remote git repository Usage: pull [flags] diff --git a/cmd/root.go b/cmd/root.go index 84a6eace0..659024f2b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -35,17 +35,17 @@ import ( // NewAirshipCTLCommand creates a root `airshipctl` command with the default commands attached func NewAirshipCTLCommand(out io.Writer) (*cobra.Command, *environment.AirshipCTLSettings, error) { - rootCmd, settings, err := NewRootCmd(out) + rootCmd, settings, err := NewRootCommand(out) return AddDefaultAirshipCTLCommands(rootCmd, settings), settings, err } -// NewRootCmd creates the root `airshipctl` command. All other commands are +// NewRootCommand creates the root `airshipctl` command. All other commands are // subcommands branching from this one -func NewRootCmd(out io.Writer) (*cobra.Command, *environment.AirshipCTLSettings, error) { +func NewRootCommand(out io.Writer) (*cobra.Command, *environment.AirshipCTLSettings, error) { settings := &environment.AirshipCTLSettings{} rootCmd := &cobra.Command{ Use: "airshipctl", - Short: "airshipctl is a unified entrypoint to various airship components", + Short: "A unified entrypoint to various airship components", SilenceErrors: true, SilenceUsage: true, PersistentPreRun: func(cmd *cobra.Command, args []string) { diff --git a/cmd/root_test.go b/cmd/root_test.go index a2a3fd48f..235176498 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -31,19 +31,19 @@ import ( func TestRoot(t *testing.T) { tests := []*testutil.CmdTest{ { - Name: "rootCmd-with-no-defaults", - CmdLine: "-h", - Cmd: getVanillaRootCmd(t), + Name: "rootCmd-with-no-subcommands", + CmdLine: "--help", + Cmd: getVanillaRootCommand(t), }, { - Name: "rootCmd-with-defaults", - CmdLine: "-h", - Cmd: getDefaultRootCmd(t), + Name: "rootCmd-with-default-subcommands", + CmdLine: "--help", + Cmd: getDefaultRootCommand(t), }, { Name: "specialized-rootCmd-with-bootstrap", - CmdLine: "-h", - Cmd: getSpecializedRootCmd(t), + CmdLine: "--help", + Cmd: getSpecializedRootCommand(t), }, } @@ -78,7 +78,7 @@ func TestFlagLoading(t *testing.T) { t.Run(tt.name, func(subTest *testing.T) { // We don't care about the output of this test, so toss // it into a throwaway &bytes.buffer{} - rootCmd, settings, err := cmd.NewRootCmd(&bytes.Buffer{}) + rootCmd, settings, err := cmd.NewRootCommand(&bytes.Buffer{}) require.NoError(t, err) rootCmd.SetArgs(tt.args) @@ -90,22 +90,22 @@ func TestFlagLoading(t *testing.T) { } } -func getVanillaRootCmd(t *testing.T) *cobra.Command { +func getVanillaRootCommand(t *testing.T) *cobra.Command { t.Helper() - rootCmd, _, err := cmd.NewRootCmd(nil) + rootCmd, _, err := cmd.NewRootCommand(nil) require.NoError(t, err, "Could not create root commands") return rootCmd } -func getDefaultRootCmd(t *testing.T) *cobra.Command { +func getDefaultRootCommand(t *testing.T) *cobra.Command { t.Helper() rootCmd, _, err := cmd.NewAirshipCTLCommand(nil) require.NoError(t, err, "Could not create root commands") return rootCmd } -func getSpecializedRootCmd(t *testing.T) *cobra.Command { - rootCmd := getVanillaRootCmd(t) +func getSpecializedRootCommand(t *testing.T) *cobra.Command { + rootCmd := getVanillaRootCommand(t) rootCmd.AddCommand(bootstrap.NewBootstrapCommand(&environment.AirshipCTLSettings{})) return rootCmd } diff --git a/cmd/secret/generate/generate.go b/cmd/secret/generate/generate.go index dbf15e7f2..0c37886e2 100644 --- a/cmd/secret/generate/generate.go +++ b/cmd/secret/generate/generate.go @@ -21,7 +21,7 @@ func NewGenerateCommand() *cobra.Command { generateRootCmd := &cobra.Command{ Use: "generate", // TODO(howell): Make this more expressive - Short: "generates various secrets", + Short: "Generate various secrets", } generateRootCmd.AddCommand(NewGenerateMasterPassphraseCommand()) diff --git a/cmd/secret/generate/masterpassphrase.go b/cmd/secret/generate/masterpassphrase.go index ee58a7a13..3bfd59c38 100644 --- a/cmd/secret/generate/masterpassphrase.go +++ b/cmd/secret/generate/masterpassphrase.go @@ -27,7 +27,7 @@ func NewGenerateMasterPassphraseCommand() *cobra.Command { masterPassphraseCmd := &cobra.Command{ Use: "masterpassphrase", // TODO(howell): Make this more expressive - Short: "generates a secure master passphrase", + Short: "Generates a secure master passphrase", Run: func(cmd *cobra.Command, args []string) { engine := secret.NewPassphraseEngine(nil) masterPassphrase := engine.GeneratePassphrase() diff --git a/cmd/secret/secret.go b/cmd/secret/secret.go index a77fb2105..967763c1d 100644 --- a/cmd/secret/secret.go +++ b/cmd/secret/secret.go @@ -25,7 +25,7 @@ func NewSecretCommand() *cobra.Command { secretRootCmd := &cobra.Command{ Use: "secret", // TODO(howell): Make this more expressive - Short: "manages secrets", + Short: "Manage secrets", } secretRootCmd.AddCommand(generate.NewGenerateCommand()) diff --git a/cmd/testdata/TestRootGoldenOutput/rootCmd-with-defaults.golden b/cmd/testdata/TestRootGoldenOutput/rootCmd-with-default-subcommands.golden similarity index 68% rename from cmd/testdata/TestRootGoldenOutput/rootCmd-with-defaults.golden rename to cmd/testdata/TestRootGoldenOutput/rootCmd-with-default-subcommands.golden index 352c2aa3b..173c14c5b 100644 --- a/cmd/testdata/TestRootGoldenOutput/rootCmd-with-defaults.golden +++ b/cmd/testdata/TestRootGoldenOutput/rootCmd-with-default-subcommands.golden @@ -1,17 +1,17 @@ -airshipctl is a unified entrypoint to various airship components +A unified entrypoint to various airship components Usage: airshipctl [command] Available Commands: bootstrap Bootstrap ephemeral Kubernetes cluster - cluster Control Kubernetes cluster - completion Generate autocompletions script for the specified shell (bash or zsh) - config Modify airshipctl config files - document manages deployment documents + cluster Manage Kubernetes clusters + completion Generate completion script for the specified shell (bash or zsh) + config Manage the airshipctl config file + document Manage deployment documents help Help about any command remote Control remote entities, i.e. hosts. - secret manages secrets + secret Manage secrets version Show the version number of airshipctl Flags: diff --git a/cmd/testdata/TestRootGoldenOutput/rootCmd-with-no-defaults.golden b/cmd/testdata/TestRootGoldenOutput/rootCmd-with-no-subcommands.golden similarity index 89% rename from cmd/testdata/TestRootGoldenOutput/rootCmd-with-no-defaults.golden rename to cmd/testdata/TestRootGoldenOutput/rootCmd-with-no-subcommands.golden index 8eb007dd6..1fe882fd7 100644 --- a/cmd/testdata/TestRootGoldenOutput/rootCmd-with-no-defaults.golden +++ b/cmd/testdata/TestRootGoldenOutput/rootCmd-with-no-subcommands.golden @@ -1,4 +1,4 @@ -airshipctl is a unified entrypoint to various airship components +A unified entrypoint to various airship components Usage: airshipctl [command] diff --git a/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden b/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden index faf35bcdb..cd12cdd5a 100644 --- a/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden +++ b/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden @@ -1,4 +1,4 @@ -airshipctl is a unified entrypoint to various airship components +A unified entrypoint to various airship components Usage: airshipctl [command] diff --git a/cmd/version.go b/cmd/version.go index 70d91f3b3..ca7d8e313 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -22,7 +22,7 @@ import ( "opendev.org/airship/airshipctl/pkg/util" ) -// NewVersionCommand prints out the versions of airshipctl and its underlying tools +// NewVersionCommand creates a command for displaying the version of airshipctl. func NewVersionCommand() *cobra.Command { versionCmd := &cobra.Command{ Use: "version", diff --git a/docs/source/cli/cli.rst b/docs/source/cli/cli.rst index 42f4bb637..3569d3057 100644 --- a/docs/source/cli/cli.rst +++ b/docs/source/cli/cli.rst @@ -19,8 +19,9 @@ AirshipCTL CLI ============== -The AirshipCTL CLI is used in conjunction with the binary created by running ``make build``. This binary, by default, -is created in the ``airshipctl/bin/`` directory. +The AirshipCTL CLI is used in conjunction with the binary created by running +``make build``. This binary, by default, is created in the ``airshipctl/bin/`` +directory. CLI Options @@ -30,15 +31,15 @@ CLI Options Prints help for a specific command or command group. -**\\-\\-debug** (Optional, default: false) +**\\-\\-debug** (default: false) Enables verbose output of commands. -**\\-\\-airshipconf** (Optional, default: `$HOME/.airship/config`) +**\\-\\-airshipconf** (default: `$HOME/.airship/config`) Path to file for airshipctl configuration. -**\\-\\-kubeconfig** (Optional, default: `$HOME/.airship/kubeconfig`) +**\\-\\-kubeconfig** (default: `$HOME/.airship/kubeconfig`) Path to kubeconfig associated with airshipctl configuration. @@ -67,11 +68,11 @@ Usage: Completion ---------- -Generate autocompletion script for airshipctl for the specified shell (bash or zsh). +Generate completion script for airshipctl for the specified shell (bash or zsh). **shell** (Required) -Shell to generate autocompletion script for. Supported values are `bash` and `zsh` +Shell to generate completion script for. Supported values are `bash` and `zsh` Usage: @@ -82,13 +83,13 @@ Usage: Examples ^^^^^^^^ -This command can generate bash autocompletion. e.g. +Save shell completion to a file :: - $ airshipctl completion bash + $ airshipctl completion bash > $HOME/.airship_completions -Which can be sourced as such: +Apply completions to the current shell :: @@ -128,22 +129,23 @@ Usage: Cluster Group ============= -Control Kubernetes cluster. +This command provides capabilities for interacting with a Kubernetes cluster, +such as getting status and deploying initial infrastructure. InitInfra ------------ Deploy initinfra components to cluster. -**cluster-type** (Optional, default:"ephemeral") +**cluster-type** (default:"ephemeral") Select cluster type to deploy initial infrastructure to, currently only ephemeral is supported. -**\\-\\-dry-run** (Optional). +**\\-\\-dry-run** Don't deliver documents to the cluster, simulate the changes instead. -**\\-\\-prune** (Optional, default:false) +**\\-\\-prune** (default: false) If set to true, command will delete all kubernetes resources that are not defined in airship documents and have airshipit.org/deployed=initinfra label @@ -159,20 +161,20 @@ Usage: Config Group ============ -Modify airshipctl config files +Manage the airshipctl config file Get-Cluster ----------- -Display cluster information. +Get cluster information from the airshipctl config. **name** (Optional, default: all defined clusters) -Displays a specific cluster if specified, or if left blank all defined clusters. +Display a specific cluster or all defined clusters if no name is provided. -**\\-\\-cluster-type** (Required). +**\\-\\-cluster-type** (Required if **name** is provided). -cluster-type for the cluster-entry in airshipctl config. Currently only ephemeral cluster types are supported. +The type of the desired cluster. Valid values are from [ephemeral|target]. Usage: @@ -183,7 +185,7 @@ Usage: Examples ^^^^^^^^ -List all the clusters airshipctl knows about: +List all the clusters: :: @@ -198,13 +200,13 @@ Display a specific cluster: Get-Context ----------- -Displays context information +Display information about contexts such as associated manifests, users, and clusters. **name** (Optional, default: all defined contexts) Displays a named context, if no name is provided display all defined contexts. -**\\-\\-current-context** (Optional, default:false) +**\\-\\-current-context** (default: false) Display the current context, supersedes the `name` argument. @@ -233,43 +235,47 @@ For a named context: :: - airshipctl config get-context e2e + airshipctl config get-context exampleContext Get-Credentials --------------- -Display a user's information. +Get user credentials from the airshipctl config. **name** (Optional, default: all defined users) -Display a specific user's information. If no name is specified, list all defined users. +Display a specific user's credentials, or all defined user credentials if no name is provided. Usage: :: - airshipctl config get-credentials + airshipctl config get-credentials Examples ^^^^^^^^ -List all the users airshipctl knows about: +List all user credentials: :: airshipctl config get-credentials -Display a specific user's information: +Display a specific user's credentials: :: - airshipctl config get-credentials e2e + airshipctl config get-credentials exampleUser Init ---- -Generate initial configuration files for airshipctl +Generate an airshipctl config file and its associated kubeConfig file. +These files will be written to the $HOME/.airship directory, and will contain +default configurations. + +.. note:: This will overwrite any existing config files in $HOME/.airship Usage: @@ -280,35 +286,34 @@ Usage: Set-Cluster ----------- -Sets a cluster entry in the airshipctl config. +Create or modify a cluster in the airshipctl config files. + +Since a cluster can be either "ephemeral" or "target", you must specify +cluster-type when managing clusters. **name** (Required) -The name of the cluster to add to airshipctl config. +The name of the cluster to add or modify in the airshipctl config file. -.. note:: +**\\-\\-certificate-authority** - Specifying a name that already exists will merge new fields on top of existing values for those fields. - -**\\-\\-certificate-authority** (Optional) - -Path to certificate-authority file for the cluster entry in airshipctl config +Path to a certificate authority file **\\-\\-certificate-authority** (Required) -Cluster-type for the cluster entry in airshipctl config +The type of the cluster to add or modify -**\\-\\-embed-certs** (Optional) +**\\-\\-embed-certs** (default: false) -Embed-certs for the cluster entry in airshipctl config +If set, embed the client certificate/key into the cluster -**\\-\\-insecure-skip-tls-verify** (Optional, default:true) +**\\-\\-insecure-skip-tls-verify** (default: true) -Insecure-skip-tls-verify for the cluster entry in airshipctl config +If set, disable certificate checking -**\\-\\-server** (Optional) +**\\-\\-server** -Server for the cluster entry in airshipctl config +Server to use for the cluster Usage: @@ -319,62 +324,72 @@ Usage: Examples ^^^^^^^^ -Set only the server field on the e2e cluster entry without touching other values: +Set the server field on the ephemeral exampleCluster: :: - airshipctl config set-cluster e2e --cluster-type=ephemeral --server=https://1.2.3.4 + airshipctl config set-cluster exampleCluster \ + --cluster-type=ephemeral \ + --server=https://1.2.3.4 -Embed certificate authority data for the e2e cluster entry: +Embed certificate authority data for the target exampleCluster: :: - airshipctl config set-cluster e2e --cluster-type=target --certificate-authority-authority=~/.airship/e2e/kubernetes.ca.crt + airshipctl config set-cluster exampleCluster \ + --cluster-type=target \ + --client-certificate-authority=$HOME/.airship/ca/kubernetes.ca.crt \ + --embed-certs -Disable cert checking for the dev cluster entry: +Disable certificate checking for the target exampleCluster: :: - airshipctl config set-cluster e2e --cluster-type=target --insecure-skip-tls-verify=true + airshipctl config set-cluster exampleCluster + --cluster-type=target \ + --insecure-skip-tls-verify -Configure client certificate: +Configure client certificate for the target exampleCluster: :: - airshipctl config set-cluster e2e --cluster-type=target --embed-certs=true --client-certificate=".airship/cert_file" + airshipctl config set-cluster exampleCluster \ + --cluster-type=target \ + --embed-certs \ + --client-certificate=$HOME/.airship/cert_file Set-Context ----------- -Switch to a new context, or update context values in the airshipctl config +Create or modify a context in the airshipctl config files. **name** (Required) -The name of the context to set. +The name of the context to add or modify in the airshipctl config file. -**\\-\\-cluster-string** +**\\-\\-cluster** -Sets the cluster for the specified context in the airshipctl config. +Set the cluster for the specified context. **\\-\\-cluster-type** -Sets the cluster-type for the specified context in the airshipctl config. +Set the cluster-type for the specified context. **\\-\\-current** -Use current context from airshipctl config. +Update the current context. **\\-\\-manifest** -Sets the manifest for the specified context in the airshipctl config. +Set the manifest for the specified context. **\\-\\-namespace** -Sets the namespace for the specified context in the airshipctl config. +Set the namespace for the specified context. **\\-\\-user** -Sets the user for the specified context in the airshipctl config. +Set the user for the specified context. Usage: @@ -385,63 +400,63 @@ Usage: Examples ^^^^^^^^ -Create a completely new e2e context entry: +Create a new context named "exampleContext": :: - airshipctl config set-context e2e --namespace=kube-system --manifest=manifest --user=auth-info --cluster-type=target + airshipctl config set-context exampleContext \ + --namespace=kube-system \ + --manifest=exampleManifest \ + --user=exampleUser + --cluster-type=target -Update the current-context to e2e: +Update the manifest of the current-context: :: - airshipctl config set-context e2e - -Update attributes of the current-context: - -:: - - airshipctl config set-context --current --manifest=manifest + airshipctl config set-context \ + --current \ + --manifest=exampleManifest Set-Credentials --------------- -Sets a user entry in the airshipctl config. +Create or modify a user credential in the airshipctl config file. + +.. note:: Specifying more than one authentication method is an error. **name** (Required) The user entry to update in airshipctl config. -.. note:: Specifying a name that already exists will merge new fields on top of existing values. - **\\-\\-client-certificate** -Path to client-certificate file for the user entry in airshipctl +Path to a certificate file. **\\-\\-client-key** -Path to client-key file for the user entry in airshipctl +Path to a key file. **\\-\\-embed-certs** -Embed client cert/key for the user entry in airshipctl +If set, embed the client certificate/key into the credential. **\\-\\-password** -Password for the user entry in airshipctl +Password for the credential .. note:: Username and Password flags are mutually exclusive with Token flag **\\-\\-token** -Token for the user entry in airshipctl +Token to use for the credential .. note:: Username and Password flags are mutually exclusive with Token flag **\\-\\-username** -Username for the user entry in airshipctl +Username for the credential .. note:: Username and Password flags are mutually exclusive with Token flag @@ -454,23 +469,36 @@ Usage: Examples ^^^^^^^^ -Set only the "client-key" field on the "cluster-admin" entry, without touching other values: +Create a new user credential with basic auth: :: - airshipctl config set-credentials cluster-admin --username=~/.kube/admin.key + airshipctl config set-credentials exampleUser \ + --username=exampleUser \ + --password=examplePassword -Set basic auth for the "cluster-admin" entry +Change the client-key of a user named admin :: - airshipctl config set-credentials cluster-admin --username=admin --password=uXFGweU9l35qcif + airshipctl config set-credentials admin \ + --client-key=$HOME/.kube/admin.key -Embed client certificate data in the "cluster-admin" entry +Change the username and password of the admin user :: - airshipctl config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true + airshipctl config set-credentials admin \ + --username=admin \ + --password=uXFGweU9l35qcif + +Embed client certificate data of the admin user + +:: + + airshipctl config set-credentials admin \ + --client-certificate=$HOME/.kube/admin.crt \ + --embed-certs .. _document-group: diff --git a/pkg/config/constants.go b/pkg/config/constants.go index d2cde8bc2..24b1b465d 100644 --- a/pkg/config/constants.go +++ b/pkg/config/constants.go @@ -54,26 +54,3 @@ const ( AirshipDefaultIsoURL = "http://localhost:8099/debian-custom.iso" AirshipDefaultRemoteType = redfish.ClientType ) - -const ( - FlagAPIServer = "server" - FlagAuthInfoName = "user" - FlagBearerToken = "token" - FlagCAFile = "certificate-authority" - FlagCertFile = "client-certificate" - FlagClusterName = "cluster" - FlagClusterType = "cluster-type" - - FlagCurrentContext = "current-context" - FlagConfigFilePath = "airshipconf" - FlagEmbedCerts = "embed-certs" - - FlagInsecure = "insecure-skip-tls-verify" - FlagKeyFile = "client-key" - FlagManifest = "manifest" - FlagNamespace = "namespace" - FlagPassword = "password" - - FlagUsername = "username" - FlagCurrent = "current" -) diff --git a/pkg/config/options.go b/pkg/config/options.go index 2096090f3..8b2e7d285 100644 --- a/pkg/config/options.go +++ b/pkg/config/options.go @@ -54,21 +54,33 @@ type ClusterOptions struct { EmbedCAData bool } +// TODO(howell): The following functions are tightly coupled with flags passed +// on the command line. We should find a way to remove this coupling, since it +// is possible to create (and validate) these objects without using the command +// line. + +// TODO(howell): strongly type the errors in this file + func (o *AuthInfoOptions) Validate() error { + // TODO(howell): This prevents a user of airshipctl from creating a + // credential with both a bearer-token and a user/password, but it does + // not prevent a user from adding a bearer-token to a credential which + // already had a user/pass and visa-versa. This could create bugs if a + // user at first chooses one method, but later switches to another. if o.Token != "" && (o.Username != "" || o.Password != "") { - return fmt.Errorf("you cannot specify more than one authentication method at the same time: --%v or --%v/--%v", - FlagBearerToken, FlagUsername, FlagPassword) + // TODO(howell): strongly type this error + return errors.New("you must specify either token or a username/password") } if !o.EmbedCertData { return nil } - if err := checkExists(FlagCertFile, o.ClientCertificate); err != nil { + if err := checkExists("client-certificate", o.ClientCertificate); err != nil { return err } - if err := checkExists(FlagKeyFile, o.ClientKey); err != nil { + if err := checkExists("client-key", o.ClientKey); err != nil { return err } @@ -81,7 +93,7 @@ func (o *ContextOptions) Validate() error { } if o.Current && o.Name != "" { - return fmt.Errorf("you cannot specify context and --%s Flag at the same time", FlagCurrent) + return errors.New("you cannot specify context and --current Flag at the same time") } // If the user simply wants to change the current context, no further validation is needed @@ -111,14 +123,14 @@ func (o *ClusterOptions) Validate() error { } if o.InsecureSkipTLSVerify && o.CertificateAuthority != "" { - return fmt.Errorf("you cannot specify a %s and %s mode at the same time", FlagCAFile, FlagInsecure) + return errors.New("you cannot specify a certificate-authority and insecure-skip-tls-verify mode at the same time") } if !o.EmbedCAData { return nil } - if err := checkExists(FlagCAFile, o.CertificateAuthority); err != nil { + if err := checkExists("certificate-authority", o.CertificateAuthority); err != nil { return err } diff --git a/pkg/environment/settings.go b/pkg/environment/settings.go index 0a9d5b228..f1b0a1dec 100644 --- a/pkg/environment/settings.go +++ b/pkg/environment/settings.go @@ -49,7 +49,7 @@ func (a *AirshipCTLSettings) InitFlags(cmd *cobra.Command) { defaultAirshipConfigPath := filepath.Join(defaultAirshipConfigDir, config.AirshipConfig) flags.StringVar( &a.AirshipConfigPath, - config.FlagConfigFilePath, + "airshipconf", "", `Path to file for airshipctl configuration. (default "`+defaultAirshipConfigPath+`")`)