Skip to content

Commit

Permalink
Support strong-typing for --target values
Browse files Browse the repository at this point in the history
A small cleanup that makes our code a little more robust.
  • Loading branch information
justinsb committed Dec 5, 2024
1 parent 3a8a13f commit c60d7a9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 17 deletions.
13 changes: 8 additions & 5 deletions cmd/kops/create_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ import (

type CreateClusterOptions struct {
cloudup.NewClusterOptions
Yes bool
Target string
Yes bool

// Target is the type of target we will operate against (direct, dry-run, terraform)
Target cloudup.Target

ControlPlaneVolumeSize int32
NodeVolumeSize int32
ContainerRuntime string
Expand Down Expand Up @@ -203,7 +206,7 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
}

cmd.Flags().BoolVarP(&options.Yes, "yes", "y", options.Yes, "Specify --yes to immediately create the cluster")
cmd.Flags().StringVar(&options.Target, "target", options.Target, fmt.Sprintf("Valid targets: %s, %s. Set this flag to %s if you want kOps to generate terraform", cloudup.TargetDirect, cloudup.TargetTerraform, cloudup.TargetTerraform))
cmd.Flags().Var(&options.Target, "target", fmt.Sprintf("Valid targets: %s, %s. Set this flag to %s if you want kOps to generate terraform", cloudup.TargetDirect, cloudup.TargetTerraform, cloudup.TargetTerraform))
cmd.RegisterFlagCompletionFunc("target", completeCreateClusterTarget(options))

// Configuration / state location
Expand Down Expand Up @@ -1008,7 +1011,7 @@ func completeNetworking(options *CreateClusterOptions) func(cmd *cobra.Command,

func completeCreateClusterTarget(options *CreateClusterOptions) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
completions := []string{
completions := []cloudup.Target{
cloudup.TargetDirect,
cloudup.TargetDryRun,
}
Expand All @@ -1017,7 +1020,7 @@ func completeCreateClusterTarget(options *CreateClusterOptions) func(cmd *cobra.
completions = append(completions, cloudup.TargetTerraform)
}
}
return completions, cobra.ShellCompDirectiveNoFileComp
return toStringSlice(completions), cobra.ShellCompDirectiveNoFileComp
}
}

Expand Down
27 changes: 19 additions & 8 deletions cmd/kops/update_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ var (
)

type UpdateClusterOptions struct {
Yes bool
Target string
Yes bool

// Target is the type of target we will operate against (direct, dry-run, terraform)
Target cloudup.Target

OutDir string
SSHPublicKey string
RunTasksOptions fi.RunTasksOptions
Expand Down Expand Up @@ -107,7 +110,7 @@ type UpdateClusterOptions struct {

func (o *UpdateClusterOptions) InitDefaults() {
o.Yes = false
o.Target = "direct"
o.Target = cloudup.TargetDirect
o.SSHPublicKey = ""
o.OutDir = ""
// By default we enforce the version skew between control plane and worker nodes
Expand Down Expand Up @@ -144,7 +147,7 @@ func NewCmdUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
}

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")
cmd.Flags().Var(&options.Target, "target", "Target - direct, terraform")
cmd.RegisterFlagCompletionFunc("target", completeUpdateClusterTarget(f, options))
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")
Expand Down Expand Up @@ -530,14 +533,14 @@ func completeUpdateClusterTarget(f commandutils.Factory, options *UpdateClusterO

cluster, _, _, directive := GetClusterForCompletion(ctx, f, nil)
if cluster == nil {
return []string{
return toStringSlice([]cloudup.Target{
cloudup.TargetDirect,
cloudup.TargetDryRun,
cloudup.TargetTerraform,
}, directive
}), directive
}

completions := []string{
completions := []cloudup.Target{
cloudup.TargetDirect,
cloudup.TargetDryRun,
}
Expand All @@ -546,8 +549,16 @@ func completeUpdateClusterTarget(f commandutils.Factory, options *UpdateClusterO
completions = append(completions, cloudup.TargetTerraform)
}
}
return completions, cobra.ShellCompDirectiveNoFileComp
return toStringSlice(completions), cobra.ShellCompDirectiveNoFileComp
}
}

func toStringSlice[T ~string](targets []T) []string {
strings := make([]string, len(targets))
for i, target := range targets {
strings[i] = string(target)
}
return strings
}

func completeLifecycleOverrides(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
Expand Down
2 changes: 1 addition & 1 deletion upup/pkg/fi/cloudup/apply_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ type ApplyClusterCmd struct {
InstanceGroups []*kops.InstanceGroup

// TargetName specifies how we are operating e.g. direct to GCE, or AWS, or dry-run, or terraform
TargetName string
TargetName Target

// Target is the fi.Target we will operate against
Target fi.CloudupTarget
Expand Down
40 changes: 37 additions & 3 deletions upup/pkg/fi/cloudup/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,42 @@ limitations under the License.

package cloudup

import (
"fmt"
"strings"

"github.com/spf13/pflag"
)

// Target is the type of target we are operating against.
type Target string

const (
TargetDirect = "direct"
TargetDryRun = "dryrun"
TargetTerraform = "terraform"
// TargetDirect means we will apply the changes directly to the cloud.
TargetDirect Target = "direct"
// TargetDryRun means we will not apply the changes but will print what would have been done.
TargetDryRun Target = "dryrun"
// TargetTerraform means we will generate terraform code.
TargetTerraform Target = "terraform"
)

// Target can be used as a flag value.
var _ pflag.Value = (*Target)(nil)

func (t *Target) String() string {
return string(*t)
}

func (t *Target) Set(value string) error {
switch strings.ToLower(value) {
case string(TargetDirect), string(TargetDryRun), string(TargetTerraform):
*t = Target(value)
return nil
default:
return fmt.Errorf("invalid target: %q", value)
}
}

func (t *Target) Type() string {
return "target"
}

0 comments on commit c60d7a9

Please sign in to comment.