Merge pull request #11926 from johngmyers/complete-update

Implement completion for "kops update cluster"
This commit is contained in:
Kubernetes Prow Robot 2021-07-05 10:16:54 -07:00 committed by GitHub
commit a5533a058e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 98 additions and 75 deletions

View File

@ -662,12 +662,13 @@ func RunCreateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *Cr
updateClusterOptions.Target = c.Target
updateClusterOptions.OutDir = c.OutDir
updateClusterOptions.admin = kubeconfig.DefaultKubecfgAdminLifetime
updateClusterOptions.ClusterName = cluster.Name
updateClusterOptions.CreateKubecfg = true
// SSHPublicKey has already been mapped
updateClusterOptions.SSHPublicKey = ""
_, err := RunUpdateCluster(ctx, f, cluster.Name, out, updateClusterOptions)
_, err := RunUpdateCluster(ctx, f, out, updateClusterOptions)
if err != nil {
return err
}

View File

@ -27,6 +27,7 @@ import (
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kops/cmd/kops/util"
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kops/pkg/kubeconfig"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kubectl/pkg/util/i18n"
@ -176,3 +177,19 @@ func buildPathOptions(options *ExportKubecfgOptions) *clientcmd.PathOptions {
return pathOptions
}
func completeKubecfgUser(cmd *cobra.Command, args []string, complete string) ([]string, cobra.ShellCompDirective) {
pathOptions := clientcmd.NewDefaultPathOptions()
config, err := pathOptions.GetStartingConfig()
if err != nil {
return commandutils.CompletionError("reading kubeconfig", err)
}
var users []string
for user := range config.AuthInfos {
users = append(users, user)
}
return users, cobra.ShellCompDirectiveNoFileComp
}

View File

@ -104,9 +104,10 @@ func RunGetAssets(ctx context.Context, f *util.Factory, out io.Writer, options *
return fmt.Errorf("--name is required")
}
updateClusterResults, err := RunUpdateCluster(ctx, f, clusterName, out, &UpdateClusterOptions{
Target: cloudup.TargetDryRun,
GetAssets: true,
updateClusterResults, err := RunUpdateCluster(ctx, f, out, &UpdateClusterOptions{
Target: cloudup.TargetDryRun,
GetAssets: true,
ClusterName: clusterName,
})
if err != nil {
return err

View File

@ -599,10 +599,10 @@ func (i *integrationTest) runTest(t *testing.T, h *testutils.IntegrationTestHarn
// We don't test it here, and it adds a dependency on kubectl
options.CreateKubecfg = false
options.ClusterName = i.clusterName
options.LifecycleOverrides = i.lifecycleOverrides
_, err := RunUpdateCluster(ctx, factory, i.clusterName, &stdout, options)
_, err := RunUpdateCluster(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running update cluster %q: %v", i.clusterName, err)
}
@ -1008,9 +1008,10 @@ func (i *integrationTest) runTestCloudformation(t *testing.T) {
// We don't test it here, and it adds a dependency on kubectl
options.CreateKubecfg = false
options.ClusterName = i.clusterName
options.LifecycleOverrides = i.lifecycleOverrides
_, err := RunUpdateCluster(ctx, factory, i.clusterName, &stdout, options)
_, err := RunUpdateCluster(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running update cluster %q: %v", i.clusterName, err)
}

View File

@ -502,8 +502,9 @@ func updateEnsureNoChanges(ctx context.Context, t *testing.T, factory *util.Fact
// We don't test it here, and it adds a dependency on kubectl
options.CreateKubecfg = false
options.ClusterName = clusterName
_, err := RunUpdateCluster(ctx, factory, clusterName, &stdout, options)
_, err := RunUpdateCluster(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running update cluster %q: %v", clusterName, err)
}
@ -517,8 +518,9 @@ func updateEnsureNoChanges(ctx context.Context, t *testing.T, factory *util.Fact
// We don't test it here, and it adds a dependency on kubectl
options.CreateKubecfg = false
options.ClusterName = clusterName
results, err := RunUpdateCluster(ctx, factory, clusterName, &stdout, options)
results, err := RunUpdateCluster(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running update cluster %q: %v", clusterName, err)
}

View File

@ -22,28 +22,16 @@ import (
"github.com/spf13/cobra"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
var (
updateLong = templates.LongDesc(i18n.T(`
Creates or updates cloud resources to match cluster desired configuration.
`))
updateExample = templates.Examples(i18n.T(`
# After cluster has been created, configure it with:
kops update cluster k8s-cluster.example.com --yes --state=s3://my-state-store
`))
updateShort = i18n.T("Update a cluster.")
)
func NewCmdUpdate(f *util.Factory, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Short: updateShort,
Long: updateLong,
Example: updateExample,
Use: "update",
Short: updateShort,
}
// subcommands

View File

@ -33,6 +33,7 @@ import (
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kops/pkg/kubeconfig"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup"
@ -44,16 +45,16 @@ import (
var (
updateClusterLong = templates.LongDesc(i18n.T(`
Create or update cloud or cluster resources to match current cluster state. If the cluster or cloud resources already
exist this command may modify those resources.
Create or update cloud or cluster resources to match the current cluster and instance group definitions.
If the cluster or cloud resources already exist this command may modify those resources.
If nodes need updating such as during a Kubernetes upgrade, a rolling-update may
be required as well.
If, such as during a Kubernetes upgrade, nodes need updating, a rolling-update may
be subsequently required.
`))
updateClusterExample = templates.Examples(i18n.T(`
# After cluster has been edited or upgraded, configure it with:
kops update cluster k8s-cluster.example.com --yes --state=s3://my-state-store --yes --admin
# After the cluster has been edited or upgraded, update the cloud resources with:
kops update cluster k8s-cluster.example.com --yes --state=s3://my-state-store --yes
`))
updateClusterShort = i18n.T("Update a cluster.")
@ -69,6 +70,8 @@ type UpdateClusterOptions struct {
// GetAssets is whether this is invoked from the CmdGetAssets.
GetAssets bool
ClusterName string
CreateKubecfg bool
admin time.Duration
user string
@ -98,40 +101,41 @@ func NewCmdUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
options.InitDefaults()
cmd := &cobra.Command{
Use: "cluster",
Short: updateClusterShort,
Long: updateClusterLong,
Example: updateClusterExample,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()
err := rootCommand.ProcessArgs(args)
if err != nil {
exitWithError(err)
}
clusterName := rootCommand.ClusterName(true)
if _, err := RunUpdateCluster(ctx, f, clusterName, out, options); err != nil {
exitWithError(err)
}
Use: "cluster [CLUSTER]",
Short: updateClusterShort,
Long: updateClusterLong,
Example: updateClusterExample,
Args: rootCommand.clusterNameArgs(&options.ClusterName),
ValidArgsFunction: commandutils.CompleteClusterName(&rootCommand, true),
RunE: func(cmd *cobra.Command, args []string) error {
_, err := RunUpdateCluster(context.TODO(), f, out, options)
return err
},
}
cmd.Flags().BoolVarP(&options.Yes, "yes", "y", options.Yes, "Create cloud resources, without --yes update is in dry run mode")
cmd.Flags().StringVar(&options.Target, "target", options.Target, "Target - direct, terraform, cloudformation")
cmd.RegisterFlagCompletionFunc("target", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{cloudup.TargetDirect, cloudup.TargetDryRun, cloudup.TargetTerraform, cloudup.TargetCloudformation}, cobra.ShellCompDirectiveNoFileComp
})
cmd.Flags().StringVar(&options.SSHPublicKey, "ssh-public-key", options.SSHPublicKey, "SSH public key to use (deprecated: use kops create secret instead)")
cmd.Flags().StringVar(&options.OutDir, "out", options.OutDir, "Path to write any local output")
cmd.MarkFlagDirname("out")
cmd.Flags().BoolVar(&options.CreateKubecfg, "create-kube-config", options.CreateKubecfg, "Will control automatically creating the kube config file on your local filesystem")
cmd.Flags().DurationVar(&options.admin, "admin", options.admin, "Also export a cluster admin user credential with the specified lifetime and add it to the cluster context")
cmd.Flags().Lookup("admin").NoOptDefVal = kubeconfig.DefaultKubecfgAdminLifetime.String()
cmd.Flags().StringVar(&options.user, "user", options.user, "Re-use an existing user in kubeconfig. Value must specify an existing user block in your kubeconfig file. Implies --create-kube-config")
cmd.RegisterFlagCompletionFunc("user", completeKubecfgUser)
cmd.Flags().BoolVar(&options.internal, "internal", options.internal, "Use the cluster's internal DNS name. Implies --create-kube-config")
cmd.Flags().BoolVar(&options.AllowKopsDowngrade, "allow-kops-downgrade", options.AllowKopsDowngrade, "Allow an older version of kOps to update the cluster than last used")
cmd.Flags().StringVar(&options.Phase, "phase", options.Phase, "Subset of tasks to run: "+strings.Join(cloudup.Phases.List(), ", "))
cmd.RegisterFlagCompletionFunc("phase", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return cloudup.Phases.List(), cobra.ShellCompDirectiveNoFileComp
})
cmd.Flags().StringSliceVar(&options.LifecycleOverrides, "lifecycle-overrides", options.LifecycleOverrides, "comma separated list of phase overrides, example: SecurityGroups=Ignore,InternetGateway=ExistsAndWarnIfChanges")
viper.BindPFlag("lifecycle-overrides", cmd.Flags().Lookup("lifecycle-overrides"))
viper.BindEnv("lifecycle-overrides", "KOPS_LIFECYCLE_OVERRIDES")
cmd.RegisterFlagCompletionFunc("lifecycle-overrides", completeLifecycleOverrides)
return cmd
}
@ -151,7 +155,7 @@ type UpdateClusterResults struct {
Cluster *kops.Cluster
}
func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string, out io.Writer, c *UpdateClusterOptions) (*UpdateClusterResults, error) {
func RunUpdateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *UpdateClusterOptions) (*UpdateClusterResults, error) {
results := &UpdateClusterResults{}
isDryrun := false
@ -198,7 +202,7 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
}
}
cluster, err := GetCluster(ctx, f, clusterName)
cluster, err := GetCluster(ctx, f, c.ClusterName)
if err != nil {
return results, err
}
@ -368,7 +372,7 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
fmt.Fprintf(sb, "Cloudformation output has been placed into %s\n", c.OutDir)
if firstRun {
cfName := "kubernetes-" + strings.Replace(clusterName, ".", "-", -1)
cfName := "kubernetes-" + strings.Replace(c.ClusterName, ".", "-", -1)
cfPath := filepath.Join(c.OutDir, "kubernetes.json")
fmt.Fprintf(sb, "Run this command to apply the configuration:\n")
fmt.Fprintf(sb, " aws cloudformation create-stack --capabilities CAPABILITY_NAMED_IAM --stack-name %s --template-body file://%s\n", cfName, cfPath)
@ -465,3 +469,21 @@ func hasKubecfg(contextName string) (bool, error) {
}
return false, nil
}
func completeLifecycleOverrides(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
split := strings.SplitAfter(toComplete, "=")
if len(split) < 2 {
// providing completion for task names is too complicated
return nil, cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace
}
if len(split) > 2 {
return commandutils.CompletionError("too many = characters", nil)
}
var completions []string
for lifecycle := range fi.LifecycleNameMap {
completions = append(completions, split[0]+lifecycle)
}
return completions, cobra.ShellCompDirectiveNoFileComp
}

View File

@ -45,16 +45,16 @@ func NewCmdVersion(f *util.Factory, out io.Writer) *cobra.Command {
Short: versionShort,
Long: versionLong,
Example: versionExample,
Args: cobra.NoArgs,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
},
RunE: func(cmd *cobra.Command, args []string) error {
return commands.RunVersion(f, out, options)
},
}
cmd.Run = func(cmd *cobra.Command, args []string) {
err := commands.RunVersion(f, out, options)
if err != nil {
exitWithError(err)
}
}
cmd.Flags().BoolVar(&options.Short, "short", options.Short, "only print the main kOps version, useful for scripting")
cmd.Flags().BoolVar(&options.Short, "short", options.Short, "only print the main kOps version. Useful for scripting.")
return cmd
}

View File

@ -5,17 +5,6 @@
Update a cluster.
### Synopsis
Creates or updates cloud resources to match cluster desired configuration.
### Examples
```
# After cluster has been created, configure it with:
kops update cluster k8s-cluster.example.com --yes --state=s3://my-state-store
```
### Options
```

View File

@ -7,19 +7,19 @@ Update a cluster.
### Synopsis
Create or update cloud or cluster resources to match current cluster state. If the cluster or cloud resources already exist this command may modify those resources.
Create or update cloud or cluster resources to match the current cluster and instance group definitions. If the cluster or cloud resources already exist this command may modify those resources.
If nodes need updating such as during a Kubernetes upgrade, a rolling-update may be required as well.
If, such as during a Kubernetes upgrade, nodes need updating, a rolling-update may be subsequently required.
```
kops update cluster [flags]
kops update cluster [CLUSTER] [flags]
```
### Examples
```
# After cluster has been edited or upgraded, configure it with:
kops update cluster k8s-cluster.example.com --yes --state=s3://my-state-store --yes --admin
# After the cluster has been edited or upgraded, update the cloud resources with:
kops update cluster k8s-cluster.example.com --yes --state=s3://my-state-store --yes
```
### Options

View File

@ -23,7 +23,7 @@ kops version [flags]
```
-h, --help help for version
--short only print the main kOps version, useful for scripting
--short only print the main kOps version. Useful for scripting.
```
### Options inherited from parent commands

View File

@ -53,14 +53,16 @@ nav:
- kops create: "cli/kops_create.md"
- kops delete: "cli/kops_delete.md"
- kops describe: "cli/kops_describe.md"
- kops distrust: "cli/kops_distrust.md"
- kops edit: "cli/kops_edit.md"
- kops export: "cli/kops_export.md"
- kops get: "cli/kops_get.md"
- kops import: "cli/kops_import.md"
- kops promote: "cli/kops_promote.md"
- kops replace: "cli/kops_replace.md"
- kops rolling-update: "cli/kops_rolling-update.md"
- kops set: "cli/kops_set.md"
- kops toolbox: "cli/kops_toolbox.md"
- kops unset: "cli/kops_unset.md"
- kops update: "cli/kops_update.md"
- kops upgrade: "cli/kops_upgrade.md"
- kops validate: "cli/kops_validate.md"