begin wiring printopts through complete commands

This commit is contained in:
juanvallejo
2018-04-05 18:39:17 -04:00
parent 4d8e5d5d7e
commit 8a7b2fdda3
33 changed files with 762 additions and 295 deletions

View File

@@ -18,6 +18,7 @@ go_library(
"create_secret.go", "create_secret.go",
"create_service.go", "create_service.go",
"create_serviceaccount.go", "create_serviceaccount.go",
"flags.go",
], ],
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/create", importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/create",
visibility = ["//build/visible_to:pkg_kubectl_cmd_create_CONSUMERS"], visibility = ["//build/visible_to:pkg_kubectl_cmd_create_CONSUMERS"],
@@ -28,6 +29,7 @@ go_library(
"//pkg/kubectl/cmd/util/editor:go_default_library", "//pkg/kubectl/cmd/util/editor:go_default_library",
"//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library", "//pkg/kubectl/util/i18n:go_default_library",
"//pkg/printers:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library",
"//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v1beta1:go_default_library",

View File

@@ -28,6 +28,7 @@ import (
"net/url" "net/url"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
kruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
@@ -38,6 +39,11 @@ import (
) )
type CreateOptions struct { type CreateOptions struct {
PrintFlags *PrintFlags
PrintObj func(obj kruntime.Object) error
DryRun bool
FilenameOptions resource.FilenameOptions FilenameOptions resource.FilenameOptions
Selector string Selector string
EditBeforeCreate bool EditBeforeCreate bool
@@ -65,6 +71,8 @@ var (
func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
options := &CreateOptions{ options := &CreateOptions{
PrintFlags: NewPrintFlags("created"),
Out: out, Out: out,
ErrOut: errOut, ErrOut: errOut,
} }
@@ -81,6 +89,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
defaultRunFunc(cmd, args) defaultRunFunc(cmd, args)
return return
} }
cmdutil.CheckErr(options.Complete(cmd))
cmdutil.CheckErr(options.ValidateArgs(cmd, args)) cmdutil.CheckErr(options.ValidateArgs(cmd, args))
cmdutil.CheckErr(options.RunCreate(f, cmd)) cmdutil.CheckErr(options.RunCreate(f, cmd))
}, },
@@ -90,7 +99,6 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmd.MarkFlagRequired("filename") cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmd.Flags().BoolVar(&options.EditBeforeCreate, "edit", options.EditBeforeCreate, "Edit the API resource before creating") cmd.Flags().BoolVar(&options.EditBeforeCreate, "edit", options.EditBeforeCreate, "Edit the API resource before creating")
cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows", cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows",
"Only relevant if --edit=true. Defaults to the line ending native to your platform.") "Only relevant if --edit=true. Defaults to the line ending native to your platform.")
@@ -101,6 +109,8 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.") cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.")
options.PrintFlags.AddFlags(cmd)
// create subcommands // create subcommands
cmd.AddCommand(NewCmdCreateNamespace(f, out)) cmd.AddCommand(NewCmdCreateNamespace(f, out))
cmd.AddCommand(NewCmdCreateQuota(f, out)) cmd.AddCommand(NewCmdCreateQuota(f, out))
@@ -150,6 +160,24 @@ func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func (o *CreateOptions) Complete(cmd *cobra.Command) error {
o.DryRun = cmdutil.GetDryRunFlag(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")
}
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObj = func(obj kruntime.Object) error {
return printer.PrintObj(obj, o.Out)
}
return nil
}
func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error { func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
// raw only makes sense for a single file resource multiple objects aren't likely to do what you want. // raw only makes sense for a single file resource multiple objects aren't likely to do what you want.
// the validator enforces this, so // the validator enforces this, so
@@ -184,9 +212,6 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
return err return err
} }
dryRun := cmdutil.GetDryRunFlag(cmd)
output := cmdutil.GetFlagString(cmd, "output")
count := 0 count := 0
err = r.Visit(func(info *resource.Info, err error) error { err = r.Visit(func(info *resource.Info, err error) error {
if err != nil { if err != nil {
@@ -202,7 +227,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
} }
} }
if !dryRun { if !o.DryRun {
if err := createAndRefresh(info); err != nil { if err := createAndRefresh(info); err != nil {
return cmdutil.AddSourceToErr("creating", info.Source, err) return cmdutil.AddSourceToErr("creating", info.Source, err)
} }
@@ -210,13 +235,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
count++ count++
shortOutput := output == "name" return o.PrintObj(info.Object)
if len(output) > 0 && !shortOutput {
return cmdutil.PrintObject(cmd, info.Object, o.Out)
}
cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, dryRun, "created")
return nil
}) })
if err != nil { if err != nil {
return err return err
@@ -295,17 +314,52 @@ func NameFromCommandArgs(cmd *cobra.Command, args []string) (string, error) {
// CreateSubcommandOptions is an options struct to support create subcommands // CreateSubcommandOptions is an options struct to support create subcommands
type CreateSubcommandOptions struct { type CreateSubcommandOptions struct {
// PrintFlags holds options necessary for obtaining a printer
PrintFlags *PrintFlags
// Name of resource being created // Name of resource being created
Name string Name string
// StructuredGenerator is the resource generator for the object being created // StructuredGenerator is the resource generator for the object being created
StructuredGenerator kubectl.StructuredGenerator StructuredGenerator kubectl.StructuredGenerator
// DryRun is true if the command should be simulated but not run against the server // DryRun is true if the command should be simulated but not run against the server
DryRun bool DryRun bool
OutputFormat string CreateAnnotation bool
PrintObj func(obj kruntime.Object) error
CmdOut io.Writer
CmdErr io.Writer
} }
func (o *CreateSubcommandOptions) Complete(cmd *cobra.Command, args []string, generator kubectl.StructuredGenerator) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
o.Name = name
o.StructuredGenerator = generator
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")
}
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObj = func(obj kruntime.Object) error {
return printer.PrintObj(obj, o.CmdOut)
}
return nil
}
// TODO(juanvallejo): remove dependency on factory here. Complete necessary bits
// from it in the Complete() method.
// RunCreateSubcommand executes a create subcommand using the specified options // RunCreateSubcommand executes a create subcommand using the specified options
func RunCreateSubcommand(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateSubcommandOptions) error { func RunCreateSubcommand(f cmdutil.Factory, options *CreateSubcommandOptions) error {
namespace, nsOverriden, err := f.DefaultNamespace() namespace, nsOverriden, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
@@ -338,25 +392,22 @@ func RunCreateSubcommand(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, o
if err != nil { if err != nil {
return err return err
} }
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, cmdutil.InternalVersionJSONEncoder()); err != nil { if err := kubectl.CreateOrUpdateAnnotation(options.CreateAnnotation, info, cmdutil.InternalVersionJSONEncoder()); err != nil {
return err return err
} }
obj = info.Object
obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object)
if err != nil { if err != nil {
return err return err
} }
// ensure we pass a versioned object to the printer
obj = info.AsVersioned()
} else { } else {
if meta, err := meta.Accessor(obj); err == nil && nsOverriden { if meta, err := meta.Accessor(obj); err == nil && nsOverriden {
meta.SetNamespace(namespace) meta.SetNamespace(namespace)
} }
} }
if useShortOutput := options.OutputFormat == "name"; useShortOutput || len(options.OutputFormat) == 0 { return options.PrintObj(obj)
cmdutil.PrintSuccess(useShortOutput, out, obj, options.DryRun, "created")
return nil
}
return cmdutil.PrintObject(cmd, obj, out)
} }

View File

@@ -62,7 +62,8 @@ type CreateClusterRoleOptions struct {
func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
c := &CreateClusterRoleOptions{ c := &CreateClusterRoleOptions{
CreateRoleOptions: &CreateRoleOptions{ CreateRoleOptions: &CreateRoleOptions{
Out: cmdOut, PrintFlags: NewPrintFlags("created"),
Out: cmdOut,
}, },
} }
cmd := &cobra.Command{ cmd := &cobra.Command{
@@ -77,9 +78,11 @@ func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command
cmdutil.CheckErr(c.RunCreateRole()) cmdutil.CheckErr(c.RunCreateRole())
}, },
} }
c.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddDryRunFlag(cmd) cmdutil.AddDryRunFlag(cmd)
cmd.Flags().StringSliceVar(&c.Verbs, "verb", c.Verbs, "Verb that applies to the resources contained in the rule") cmd.Flags().StringSliceVar(&c.Verbs, "verb", c.Verbs, "Verb that applies to the resources contained in the rule")
cmd.Flags().StringSliceVar(&c.NonResourceURLs, "non-resource-url", c.NonResourceURLs, "A partial url that user should have access to.") cmd.Flags().StringSliceVar(&c.NonResourceURLs, "non-resource-url", c.NonResourceURLs, "A partial url that user should have access to.")
@@ -172,10 +175,5 @@ func (c *CreateClusterRoleOptions) RunCreateRole() error {
} }
} }
if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 { return c.PrintObj(clusterRole)
cmdutil.PrintSuccess(useShortOutput, c.Out, clusterRole, c.DryRun, "created")
return nil
}
return c.PrintObject(clusterRole)
} }

View File

@@ -36,8 +36,19 @@ var (
kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1`)) kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1`))
) )
type ClusterRoleBindingOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// ClusterRoleBinding is a command to ease creating ClusterRoleBindings. // ClusterRoleBinding is a command to ease creating ClusterRoleBindings.
func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ClusterRoleBindingOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", Use: "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -45,13 +56,15 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.
Long: clusterRoleBindingLong, Long: clusterRoleBindingLong,
Example: clusterRoleBindingExample, Example: clusterRoleBindingExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateClusterRoleBinding(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ClusterRoleBindingV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.ClusterRoleBindingV1GeneratorName)
cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole this ClusterRoleBinding should reference")) cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole this ClusterRoleBinding should reference"))
cmd.MarkFlagCustom("clusterrole", "__kubectl_get_resource_clusterrole") cmd.MarkFlagCustom("clusterrole", "__kubectl_get_resource_clusterrole")
@@ -61,12 +74,12 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.
return cmd return cmd
} }
// CreateClusterRoleBinding is the implementation of the create clusterrolebinding command. func (o *ClusterRoleBindingOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ClusterRoleBindingV1GeneratorName: case cmdutil.ClusterRoleBindingV1GeneratorName:
@@ -80,10 +93,11 @@ func CreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Co
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateClusterRoleBinding is the implementation of the create clusterrolebinding command.
}) func (o *ClusterRoleBindingOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -57,8 +57,19 @@ var (
kubectl create configmap my-config --from-env-file=path/to/bar.env`)) kubectl create configmap my-config --from-env-file=path/to/bar.env`))
) )
type ConfigMapOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// ConfigMap is a command to ease creating ConfigMaps. // ConfigMap is a command to ease creating ConfigMaps.
func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ConfigMapOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -67,13 +78,15 @@ func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: configMapLong, Long: configMapLong,
Example: configMapExample, Example: configMapExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateConfigMap(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ConfigMapV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.ConfigMapV1GeneratorName)
cmd.Flags().StringSlice("from-file", []string{}, "Key file can be specified using its file path, in which case file basename will be used as configmap key, or optionally with a key and file path, in which case the given key will be used. Specifying a directory will iterate each named file in the directory whose basename is a valid configmap key.") cmd.Flags().StringSlice("from-file", []string{}, "Key file can be specified using its file path, in which case file basename will be used as configmap key, or optionally with a key and file path, in which case the given key will be used. Specifying a directory will iterate each named file in the directory whose basename is a valid configmap key.")
cmd.Flags().StringArray("from-literal", []string{}, "Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)") cmd.Flags().StringArray("from-literal", []string{}, "Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)")
@@ -82,12 +95,12 @@ func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
return cmd return cmd
} }
// CreateConfigMap is the implementation of the create configmap command. func (o *ConfigMapOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateConfigMap(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ConfigMapV1GeneratorName: case cmdutil.ConfigMapV1GeneratorName:
@@ -101,10 +114,11 @@ func CreateConfigMap(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, ar
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateConfigMap is the implementation of the create configmap command.
}) func (o *ConfigMapOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -36,10 +36,22 @@ var (
kubectl create deployment my-dep --image=busybox`)) kubectl create deployment my-dep --image=busybox`))
) )
type DeploymentOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateDeployment is a macro command to create a new deployment. // NewCmdCreateDeployment is a macro command to create a new deployment.
// This command is better known to users as `kubectl create deployment`. // This command is better known to users as `kubectl create deployment`.
// Note that this command overlaps significantly with the `kubectl run` command. // Note that this command overlaps significantly with the `kubectl run` command.
func NewCmdCreateDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { func NewCmdCreateDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command {
options := &DeploymentOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
CmdErr: cmdErr,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "deployment NAME --image=image [--dry-run]", Use: "deployment NAME --image=image [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -48,13 +60,15 @@ func NewCmdCreateDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.
Long: deploymentLong, Long: deploymentLong,
Example: deploymentExample, Example: deploymentExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := createDeployment(f, cmdOut, cmdErr, cmd, args) cmdutil.CheckErr(options.Complete(f, cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, "") cmdutil.AddGeneratorFlags(cmd, "")
cmd.Flags().StringSlice("image", []string{}, "Image name to run.") cmd.Flags().StringSlice("image", []string{}, "Image name to run.")
cmd.MarkFlagRequired("image") cmd.MarkFlagRequired("image")
@@ -102,14 +116,8 @@ func generatorFromName(
return nil, false return nil, false
} }
// createDeployment func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
// 1. Reads user config values from Cobra. name, err := NameFromCommandArgs(cmd, args)
// 2. Sets up the correct Generator object.
// 3. Calls RunCreateSubcommand.
func createDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer,
cmd *cobra.Command, args []string) error {
deploymentName, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
@@ -123,27 +131,30 @@ func createDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer,
if len(generatorName) == 0 { if len(generatorName) == 0 {
generatorName = cmdutil.DeploymentBasicAppsV1GeneratorName generatorName = cmdutil.DeploymentBasicAppsV1GeneratorName
generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), cmdErr) generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), o.CreateSubcommandOptions.CmdErr)
if err != nil { if err != nil {
return err return err
} }
if generatorNameTemp != generatorName { if generatorNameTemp != generatorName {
cmdutil.Warning(cmdErr, generatorName, generatorNameTemp) cmdutil.Warning(o.CreateSubcommandOptions.CmdErr, generatorName, generatorNameTemp)
} else { } else {
generatorName = generatorNameTemp generatorName = generatorNameTemp
} }
} }
imageNames := cmdutil.GetFlagStringSlice(cmd, "image") imageNames := cmdutil.GetFlagStringSlice(cmd, "image")
generator, ok := generatorFromName(generatorName, imageNames, deploymentName) generator, ok := generatorFromName(generatorName, imageNames, name)
if !ok { if !ok {
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ return o.CreateSubcommandOptions.Complete(cmd, args, generator)
Name: deploymentName, }
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd), // createDeployment
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // 1. Reads user config values from Cobra.
}) // 2. Sets up the correct Generator object.
// 3. Calls RunCreateSubcommand.
func (o *DeploymentOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -123,13 +123,13 @@ func TestCreateDeploymentNoImage(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
ns := legacyscheme.Codecs ns := legacyscheme.Codecs
fakeDiscovery := "{\"kind\":\"APIResourceList\",\"apiVersion\":\"v1\",\"groupVersion\":\"apps/v1\",\"resources\":[{\"name\":\"deployments\",\"singularName\":\"\",\"namespaced\":true,\"kind\":\"Deployment\",\"verbs\":[\"create\",\"delete\",\"deletecollection\",\"get\",\"list\",\"patch\",\"update\",\"watch\"],\"shortNames\":[\"deploy\"],\"categories\":[\"all\"]}]}"
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
return &http.Response{ return &http.Response{
StatusCode: http.StatusOK, StatusCode: http.StatusOK,
Body: ioutil.NopCloser(&bytes.Buffer{}), Body: ioutil.NopCloser(bytes.NewBuffer([]byte(fakeDiscovery))),
}, nil }, nil
}), }),
} }
@@ -137,9 +137,23 @@ func TestCreateDeploymentNoImage(t *testing.T) {
tf.Namespace = "test" tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdCreateDeployment(tf, buf, buf) errBuff := bytes.NewBuffer([]byte{})
cmd.Flags().Set("dry-run", "true") cmd := NewCmdCreateDeployment(tf, buf, errBuff)
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
err := createDeployment(tf, buf, buf, cmd, []string{depName}) options := &DeploymentOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: buf,
CmdErr: errBuff,
DryRun: true,
},
}
err := options.Complete(tf, cmd, []string{depName})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = options.Run(tf)
assert.Error(t, err, "at least one image must be specified") assert.Error(t, err, "at least one image must be specified")
} }

View File

@@ -25,6 +25,7 @@ import (
batchv1 "k8s.io/api/batch/v1" batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1" batchv1beta1 "k8s.io/api/batch/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1" clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
@@ -42,6 +43,10 @@ var (
) )
type CreateJobOptions struct { type CreateJobOptions struct {
PrintFlags *PrintFlags
PrintObj func(obj runtime.Object) error
Name string Name string
From string From string
@@ -57,7 +62,8 @@ type CreateJobOptions struct {
// NewCmdCreateJob is a command to ease creating Jobs from CronJobs. // NewCmdCreateJob is a command to ease creating Jobs from CronJobs.
func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
c := &CreateJobOptions{ c := &CreateJobOptions{
Out: cmdOut, PrintFlags: NewPrintFlags("created"),
Out: cmdOut,
} }
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "job NAME [--from=CRONJOB]", Use: "job NAME [--from=CRONJOB]",
@@ -69,9 +75,11 @@ func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmdutil.CheckErr(c.RunCreateJob()) cmdutil.CheckErr(c.RunCreateJob())
}, },
} }
c.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddDryRunFlag(cmd) cmdutil.AddDryRunFlag(cmd)
cmd.Flags().String("from", "", "The name of the resource to create a Job from (only cronjob is supported).") cmd.Flags().String("from", "", "The name of the resource to create a Job from (only cronjob is supported).")
@@ -100,6 +108,18 @@ func (c *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
c.Cmd = cmd c.Cmd = cmd
c.OutputFormat = cmdutil.GetFlagString(cmd, "output") c.OutputFormat = cmdutil.GetFlagString(cmd, "output")
if c.DryRun {
c.PrintFlags.Complete("%s (dry run)")
}
printer, err := c.PrintFlags.ToPrinter()
if err != nil {
return err
}
c.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, c.Out)
}
return nil return nil
} }
@@ -150,10 +170,5 @@ func (c *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error {
} }
} }
if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 { return c.PrintObj(job)
cmdutil.PrintSuccess(useShortOutput, c.Out, job, c.DryRun, "created")
return nil
}
return cmdutil.PrintObject(c.Cmd, job, c.Out)
} }

View File

@@ -84,13 +84,24 @@ func TestCreateJobFromCronJob(t *testing.T) {
f := cmdtesting.NewTestFactory() f := cmdtesting.NewTestFactory()
defer f.Cleanup() defer f.Cleanup()
printFlags := NewPrintFlags("created")
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmdOptions := &CreateJobOptions{ cmdOptions := &CreateJobOptions{
Name: testJobName, PrintFlags: printFlags,
Namespace: testNamespaceName, Name: testJobName,
Client: clientset.BatchV1(), Namespace: testNamespaceName,
Out: buf, Client: clientset.BatchV1(),
Cmd: NewCmdCreateJob(f, buf), Out: buf,
Cmd: NewCmdCreateJob(f, buf),
PrintObj: func(obj runtime.Object) error {
p, err := printFlags.ToPrinter()
if err != nil {
return err
}
return p.PrintObj(obj, buf)
},
} }
err := cmdOptions.createJob(cronJob) err := cmdOptions.createJob(cronJob)

View File

@@ -36,8 +36,19 @@ var (
kubectl create namespace my-namespace`)) kubectl create namespace my-namespace`))
) )
type NamespaceOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateNamespace is a macro command to create a new namespace // NewCmdCreateNamespace is a macro command to create a new namespace
func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &NamespaceOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "namespace NAME [--dry-run]", Use: "namespace NAME [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -46,24 +57,26 @@ func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: namespaceLong, Long: namespaceLong,
Example: namespaceExample, Example: namespaceExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateNamespace(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName)
return cmd return cmd
} }
// CreateNamespace implements the behavior to run the create namespace command func (o *NamespaceOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateNamespace(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.NamespaceV1GeneratorName: case cmdutil.NamespaceV1GeneratorName:
@@ -71,10 +84,11 @@ func CreateNamespace(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, ar
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateNamespace implements the behavior to run the create namespace command
}) func (o *NamespaceOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -41,8 +41,19 @@ var (
kubectl create pdb my-pdb --selector=app=nginx --min-available=50%`)) kubectl create pdb my-pdb --selector=app=nginx --min-available=50%`))
) )
type PodDisruptionBudgetOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreatePodDisruptionBudget is a macro command to create a new pod disruption budget. // NewCmdCreatePodDisruptionBudget is a macro command to create a new pod disruption budget.
func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &PodDisruptionBudgetOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "poddisruptionbudget NAME --selector=SELECTOR --min-available=N [--dry-run]", Use: "poddisruptionbudget NAME --selector=SELECTOR --min-available=N [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -51,14 +62,15 @@ func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra
Long: pdbLong, Long: pdbLong,
Example: pdbExample, Example: pdbExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreatePodDisruptionBudget(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.PodDisruptionBudgetV2GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.PodDisruptionBudgetV2GeneratorName)
cmd.Flags().String("min-available", "", i18n.T("The minimum number or percentage of available pods this budget requires.")) cmd.Flags().String("min-available", "", i18n.T("The minimum number or percentage of available pods this budget requires."))
@@ -67,12 +79,12 @@ func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra
return cmd return cmd
} }
// CreatePodDisruptionBudget implements the behavior to run the create pdb command. func (o *PodDisruptionBudgetOpts) Complete(cmd *cobra.Command, args []string) error {
func CreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.PodDisruptionBudgetV1GeneratorName: case cmdutil.PodDisruptionBudgetV1GeneratorName:
@@ -91,10 +103,11 @@ func CreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.C
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreatePodDisruptionBudget implements the behavior to run the create pdb command.
}) func (o *PodDisruptionBudgetOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -50,12 +50,34 @@ func TestCreatePdb(t *testing.T) {
tf.Namespace = "test" tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
outputFormat := "name"
cmd := NewCmdCreatePodDisruptionBudget(tf, buf) cmd := NewCmdCreatePodDisruptionBudget(tf, buf)
cmd.Flags().Set("min-available", "1") cmd.Flags().Set("min-available", "1")
cmd.Flags().Set("selector", "app=rails") cmd.Flags().Set("selector", "app=rails")
cmd.Flags().Set("dry-run", "true") cmd.Flags().Set("dry-run", "true")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", outputFormat)
CreatePodDisruptionBudget(tf, buf, cmd, []string{pdbName})
printFlags := NewPrintFlags("created")
printFlags.OutputFormat = &outputFormat
options := &PodDisruptionBudgetOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: printFlags,
CmdOut: buf,
Name: pdbName,
},
}
err := options.Complete(cmd, []string{pdbName})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = options.Run(tf)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedOutput := "poddisruptionbudget.policy/" + pdbName + "\n" expectedOutput := "poddisruptionbudget.policy/" + pdbName + "\n"
if buf.String() != expectedOutput { if buf.String() != expectedOutput {
t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String())

View File

@@ -39,8 +39,19 @@ var (
kubectl create priorityclass default-priority --value=1000 --global-default=true --description="default priority"`)) kubectl create priorityclass default-priority --value=1000 --global-default=true --description="default priority"`))
) )
type PriorityClassOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreatePriorityClass is a macro command to create a new priorityClass. // NewCmdCreatePriorityClass is a macro command to create a new priorityClass.
func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &PriorityClassOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run]", Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -49,13 +60,15 @@ func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma
Long: pcLong, Long: pcLong,
Example: pcExample, Example: pcExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(CreatePriorityClass(f, cmdOut, cmd, args)) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.PriorityClassV1Alpha1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.PriorityClassV1Alpha1GeneratorName)
cmd.Flags().Int32("value", 0, i18n.T("the value of this priority class.")) cmd.Flags().Int32("value", 0, i18n.T("the value of this priority class."))
@@ -64,12 +77,12 @@ func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma
return cmd return cmd
} }
// CreatePriorityClass implements the behavior to run the create priorityClass command. func (o *PriorityClassOpts) Complete(cmd *cobra.Command, args []string) error {
func CreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.PriorityClassV1Alpha1GeneratorName: case cmdutil.PriorityClassV1Alpha1GeneratorName:
@@ -82,10 +95,11 @@ func CreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreatePriorityClass implements the behavior to run the create priorityClass command.
}) func (o *PriorityClassOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -49,13 +49,35 @@ func TestCreatePriorityClass(t *testing.T) {
tf.ClientConfigVal = &restclient.Config{} tf.ClientConfigVal = &restclient.Config{}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
outputFormat := "name"
cmd := NewCmdCreatePriorityClass(tf, buf) cmd := NewCmdCreatePriorityClass(tf, buf)
cmd.Flags().Set("value", "1000") cmd.Flags().Set("value", "1000")
cmd.Flags().Set("global-default", "true") cmd.Flags().Set("global-default", "true")
cmd.Flags().Set("description", "my priority") cmd.Flags().Set("description", "my priority")
cmd.Flags().Set("dry-run", "true") cmd.Flags().Set("dry-run", "true")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", outputFormat)
CreatePriorityClass(tf, buf, cmd, []string{pcName})
printFlags := NewPrintFlags("created")
printFlags.OutputFormat = &outputFormat
options := &PriorityClassOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: printFlags,
CmdOut: buf,
Name: pcName,
},
}
err := options.Complete(cmd, []string{pcName})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = options.Run(tf)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedOutput := "priorityclass.scheduling.k8s.io/" + pcName + "\n" expectedOutput := "priorityclass.scheduling.k8s.io/" + pcName + "\n"
if buf.String() != expectedOutput { if buf.String() != expectedOutput {
t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String())

View File

@@ -39,8 +39,19 @@ var (
kubectl create quota best-effort --hard=pods=100 --scopes=BestEffort`)) kubectl create quota best-effort --hard=pods=100 --scopes=BestEffort`))
) )
type QuotaOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateQuota is a macro command to create a new quota // NewCmdCreateQuota is a macro command to create a new quota
func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &QuotaOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "quota NAME [--hard=key1=value1,key2=value2] [--scopes=Scope1,Scope2] [--dry-run=bool]", Use: "quota NAME [--hard=key1=value1,key2=value2] [--scopes=Scope1,Scope2] [--dry-run=bool]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -49,26 +60,27 @@ func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: quotaLong, Long: quotaLong,
Example: quotaExample, Example: quotaExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateQuota(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ResourceQuotaV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.ResourceQuotaV1GeneratorName)
cmd.Flags().String("hard", "", i18n.T("A comma-delimited set of resource=quantity pairs that define a hard limit.")) cmd.Flags().String("hard", "", i18n.T("A comma-delimited set of resource=quantity pairs that define a hard limit."))
cmd.Flags().String("scopes", "", i18n.T("A comma-delimited set of quota scopes that must all match each object tracked by the quota.")) cmd.Flags().String("scopes", "", i18n.T("A comma-delimited set of quota scopes that must all match each object tracked by the quota."))
return cmd return cmd
} }
// CreateQuota implements the behavior to run the create quota command func (o *QuotaOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateQuota(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ResourceQuotaV1GeneratorName: case cmdutil.ResourceQuotaV1GeneratorName:
@@ -80,10 +92,11 @@ func CreateQuota(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args [
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateQuota implements the behavior to run the create quota command
}) func (o *QuotaOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -100,6 +100,8 @@ type ResourceOptions struct {
} }
type CreateRoleOptions struct { type CreateRoleOptions struct {
PrintFlags *PrintFlags
Name string Name string
Verbs []string Verbs []string
Resources []ResourceOptions Resources []ResourceOptions
@@ -111,12 +113,14 @@ type CreateRoleOptions struct {
Client clientgorbacv1.RbacV1Interface Client clientgorbacv1.RbacV1Interface
Mapper meta.RESTMapper Mapper meta.RESTMapper
Out io.Writer Out io.Writer
PrintObject func(obj runtime.Object) error PrintObj func(obj runtime.Object) error
} }
// Role is a command to ease creating Roles. // Role is a command to ease creating Roles.
func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
c := &CreateRoleOptions{ c := &CreateRoleOptions{
PrintFlags: NewPrintFlags("created"),
Out: cmdOut, Out: cmdOut,
} }
cmd := &cobra.Command{ cmd := &cobra.Command{
@@ -131,9 +135,11 @@ func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmdutil.CheckErr(c.RunCreateRole()) cmdutil.CheckErr(c.RunCreateRole())
}, },
} }
c.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddDryRunFlag(cmd) cmdutil.AddDryRunFlag(cmd)
cmd.Flags().StringSliceVar(&c.Verbs, "verb", c.Verbs, "Verb that applies to the resources contained in the rule") cmd.Flags().StringSliceVar(&c.Verbs, "verb", c.Verbs, "Verb that applies to the resources contained in the rule")
cmd.Flags().StringSlice("resource", []string{}, "Resource that the rule applies to") cmd.Flags().StringSlice("resource", []string{}, "Resource that the rule applies to")
@@ -198,13 +204,20 @@ func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
c.DryRun = cmdutil.GetDryRunFlag(cmd) c.DryRun = cmdutil.GetDryRunFlag(cmd)
c.OutputFormat = cmdutil.GetFlagString(cmd, "output") c.OutputFormat = cmdutil.GetFlagString(cmd, "output")
c.Namespace, _, err = f.DefaultNamespace() if c.DryRun {
c.PrintFlags.Complete("%s (dry run)")
}
printer, err := c.PrintFlags.ToPrinter()
if err != nil { if err != nil {
return err return err
} }
c.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, c.Out)
}
c.PrintObject = func(obj runtime.Object) error { c.Namespace, _, err = f.DefaultNamespace()
return cmdutil.PrintObject(cmd, obj, c.Out) if err != nil {
return err
} }
clientset, err := f.KubernetesClientSet() clientset, err := f.KubernetesClientSet()
@@ -292,12 +305,7 @@ func (c *CreateRoleOptions) RunCreateRole() error {
} }
} }
if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 { return c.PrintObj(role)
cmdutil.PrintSuccess(useShortOutput, c.Out, role, c.DryRun, "created")
return nil
}
return c.PrintObject(role)
} }
func arrayContains(s []string, e string) bool { func arrayContains(s []string, e string) bool {

View File

@@ -371,14 +371,17 @@ func TestComplete(t *testing.T) {
expectErr bool expectErr bool
}{ }{
"test-missing-name": { "test-missing-name": {
params: []string{}, params: []string{},
roleOptions: &CreateRoleOptions{}, roleOptions: &CreateRoleOptions{
expectErr: true, PrintFlags: NewPrintFlags("created"),
},
expectErr: true,
}, },
"test-duplicate-verbs": { "test-duplicate-verbs": {
params: []string{roleName}, params: []string{roleName},
roleOptions: &CreateRoleOptions{ roleOptions: &CreateRoleOptions{
Name: roleName, PrintFlags: NewPrintFlags("created"),
Name: roleName,
Verbs: []string{ Verbs: []string{
"get", "get",
"watch", "watch",
@@ -410,7 +413,8 @@ func TestComplete(t *testing.T) {
"test-verball": { "test-verball": {
params: []string{roleName}, params: []string{roleName},
roleOptions: &CreateRoleOptions{ roleOptions: &CreateRoleOptions{
Name: roleName, PrintFlags: NewPrintFlags("created"),
Name: roleName,
Verbs: []string{ Verbs: []string{
"get", "get",
"watch", "watch",
@@ -438,6 +442,7 @@ func TestComplete(t *testing.T) {
"test-duplicate-resourcenames": { "test-duplicate-resourcenames": {
params: []string{roleName}, params: []string{roleName},
roleOptions: &CreateRoleOptions{ roleOptions: &CreateRoleOptions{
PrintFlags: NewPrintFlags("created"),
Name: roleName, Name: roleName,
Verbs: []string{"*"}, Verbs: []string{"*"},
ResourceNames: []string{"foo", "foo"}, ResourceNames: []string{"foo", "foo"},
@@ -462,6 +467,7 @@ func TestComplete(t *testing.T) {
"test-valid-complete-case": { "test-valid-complete-case": {
params: []string{roleName}, params: []string{roleName},
roleOptions: &CreateRoleOptions{ roleOptions: &CreateRoleOptions{
PrintFlags: NewPrintFlags("created"),
Name: roleName, Name: roleName,
Verbs: []string{"*"}, Verbs: []string{"*"},
ResourceNames: []string{"foo"}, ResourceNames: []string{"foo"},

View File

@@ -36,8 +36,19 @@ var (
kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1`)) kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1`))
) )
type RoleBindingOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// RoleBinding is a command to ease creating RoleBindings. // RoleBinding is a command to ease creating RoleBindings.
func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &RoleBindingOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", Use: "rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -45,13 +56,15 @@ func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command
Long: roleBindingLong, Long: roleBindingLong,
Example: roleBindingExample, Example: roleBindingExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateRoleBinding(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.RoleBindingV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.RoleBindingV1GeneratorName)
cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole this RoleBinding should reference")) cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole this RoleBinding should reference"))
cmd.Flags().String("role", "", i18n.T("Role this RoleBinding should reference")) cmd.Flags().String("role", "", i18n.T("Role this RoleBinding should reference"))
@@ -61,11 +74,12 @@ func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command
return cmd return cmd
} }
func CreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { func (o *RoleBindingOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.RoleBindingV1GeneratorName: case cmdutil.RoleBindingV1GeneratorName:
@@ -80,10 +94,10 @@ func CreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command,
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), func (o *RoleBindingOpts) Run(f cmdutil.Factory) error {
}) return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -73,8 +73,19 @@ var (
kubectl create secret generic my-secret --from-env-file=path/to/bar.env`)) kubectl create secret generic my-secret --from-env-file=path/to/bar.env`))
) )
type SecretGenericOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values // NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values
func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &SecretGenericOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -82,13 +93,15 @@ func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma
Long: secretLong, Long: secretLong,
Example: secretExample, Example: secretExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretGeneric(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretV1GeneratorName)
cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.") cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.")
cmd.Flags().StringArray("from-literal", []string{}, "Specify a key and literal value to insert in secret (i.e. mykey=somevalue)") cmd.Flags().StringArray("from-literal", []string{}, "Specify a key and literal value to insert in secret (i.e. mykey=somevalue)")
@@ -98,12 +111,12 @@ func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma
return cmd return cmd
} }
// CreateSecretGeneric is the implementation of the create secret generic command func (o *SecretGenericOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.SecretV1GeneratorName: case cmdutil.SecretV1GeneratorName:
@@ -118,12 +131,13 @@ func CreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateSecretGeneric is the implementation of the create secret generic command
}) func (o *SecretGenericOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }
var ( var (
@@ -147,8 +161,19 @@ var (
kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`)) kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`))
) )
type SecretDockerRegistryOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries // NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries
func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &SecretDockerRegistryOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]", Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -156,13 +181,15 @@ func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobr
Long: secretForDockerRegistryLong, Long: secretForDockerRegistryLong,
Example: secretForDockerRegistryExample, Example: secretForDockerRegistryExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretDockerRegistry(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForDockerRegistryV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForDockerRegistryV1GeneratorName)
cmd.Flags().String("docker-username", "", i18n.T("Username for Docker registry authentication")) cmd.Flags().String("docker-username", "", i18n.T("Username for Docker registry authentication"))
cmd.MarkFlagRequired("docker-username") cmd.MarkFlagRequired("docker-username")
@@ -177,12 +204,12 @@ func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobr
return cmd return cmd
} }
// CreateSecretDockerRegistry is the implementation of the create secret docker-registry command func (o *SecretDockerRegistryOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
fromFileFlag := cmdutil.GetFlagStringSlice(cmd, "from-file") fromFileFlag := cmdutil.GetFlagStringSlice(cmd, "from-file")
if len(fromFileFlag) == 0 { if len(fromFileFlag) == 0 {
requiredFlags := []string{"docker-username", "docker-password", "docker-server"} requiredFlags := []string{"docker-username", "docker-password", "docker-server"}
@@ -208,12 +235,13 @@ func CreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateSecretDockerRegistry is the implementation of the create secret docker-registry command
}) func (o *SecretDockerRegistryOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }
var ( var (
@@ -228,8 +256,19 @@ var (
kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key`)) kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key`))
) )
type SecretTLSOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateSecretTLS is a macro command for creating secrets to work with Docker registries // NewCmdCreateSecretTLS is a macro command for creating secrets to work with Docker registries
func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &SecretTLSOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]", Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -237,13 +276,15 @@ func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: secretForTLSLong, Long: secretForTLSLong,
Example: secretForTLSExample, Example: secretForTLSExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretTLS(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForTLSV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForTLSV1GeneratorName)
cmd.Flags().String("cert", "", i18n.T("Path to PEM encoded public key certificate.")) cmd.Flags().String("cert", "", i18n.T("Path to PEM encoded public key certificate."))
cmd.Flags().String("key", "", i18n.T("Path to private key associated with given certificate.")) cmd.Flags().String("key", "", i18n.T("Path to private key associated with given certificate."))
@@ -251,12 +292,12 @@ func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
return cmd return cmd
} }
// CreateSecretTLS is the implementation of the create secret tls command func (o *SecretTLSOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
requiredFlags := []string{"cert", "key"} requiredFlags := []string{"cert", "key"}
for _, requiredFlag := range requiredFlags { for _, requiredFlag := range requiredFlags {
if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 { if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 {
@@ -275,10 +316,11 @@ func CreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, ar
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateSecretTLS is the implementation of the create secret tls command
}) func (o *SecretTLSOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -61,8 +61,19 @@ func addPortFlags(cmd *cobra.Command) {
cmd.Flags().StringSlice("tcp", []string{}, "Port pairs can be specified as '<port>:<targetPort>'.") cmd.Flags().StringSlice("tcp", []string{}, "Port pairs can be specified as '<port>:<targetPort>'.")
} }
type ServiceClusterIPOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceClusterIP is a command to create a ClusterIP service // NewCmdCreateServiceClusterIP is a command to create a ClusterIP service
func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceClusterIPOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "clusterip NAME [--tcp=<port>:<targetPort>] [--dry-run]", Use: "clusterip NAME [--tcp=<port>:<targetPort>] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -70,13 +81,15 @@ func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Co
Long: serviceClusterIPLong, Long: serviceClusterIPLong,
Example: serviceClusterIPExample, Example: serviceClusterIPExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceClusterIP(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceClusterIPGeneratorV1Name) cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceClusterIPGeneratorV1Name)
addPortFlags(cmd) addPortFlags(cmd)
cmd.Flags().String("clusterip", "", i18n.T("Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).")) cmd.Flags().String("clusterip", "", i18n.T("Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing)."))
@@ -87,12 +100,12 @@ func errUnsupportedGenerator(cmd *cobra.Command, generatorName string) error {
return cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName) return cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName)
} }
// CreateServiceClusterIP is the implementation of the create service clusterip command func (o *ServiceClusterIPOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceClusterIPGeneratorV1Name: case cmdutil.ServiceClusterIPGeneratorV1Name:
@@ -105,12 +118,13 @@ func CreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comm
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateServiceClusterIP is the implementation of the create service clusterip command
}) func (o *ServiceClusterIPOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }
var ( var (
@@ -122,8 +136,19 @@ var (
kubectl create service nodeport my-ns --tcp=5678:8080`)) kubectl create service nodeport my-ns --tcp=5678:8080`))
) )
type ServiceNodePortOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceNodePort is a macro command for creating a NodePort service // NewCmdCreateServiceNodePort is a macro command for creating a NodePort service
func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceNodePortOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]", Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -131,25 +156,27 @@ func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Com
Long: serviceNodePortLong, Long: serviceNodePortLong,
Example: serviceNodePortExample, Example: serviceNodePortExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceNodePort(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceNodePortGeneratorV1Name) cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceNodePortGeneratorV1Name)
cmd.Flags().Int("node-port", 0, "Port used to expose the service on each node in a cluster.") cmd.Flags().Int("node-port", 0, "Port used to expose the service on each node in a cluster.")
addPortFlags(cmd) addPortFlags(cmd)
return cmd return cmd
} }
// CreateServiceNodePort is the implementation of the create service nodeport command func (o *ServiceNodePortOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceNodePortGeneratorV1Name: case cmdutil.ServiceNodePortGeneratorV1Name:
@@ -163,12 +190,13 @@ func CreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comma
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateServiceNodePort is the implementation of the create service nodeport command
}) func (o *ServiceNodePortOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }
var ( var (
@@ -180,8 +208,19 @@ var (
kubectl create service loadbalancer my-lbs --tcp=5678:8080`)) kubectl create service loadbalancer my-lbs --tcp=5678:8080`))
) )
type ServiceLoadBalancerOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service // NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service
func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceLoadBalancerOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]", Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -189,24 +228,26 @@ func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra
Long: serviceLoadBalancerLong, Long: serviceLoadBalancerLong,
Example: serviceLoadBalancerExample, Example: serviceLoadBalancerExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceLoadBalancer(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceLoadBalancerGeneratorV1Name) cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceLoadBalancerGeneratorV1Name)
addPortFlags(cmd) addPortFlags(cmd)
return cmd return cmd
} }
// CreateServiceLoadBalancer is the implementation of the create service loadbalancer command func (o *ServiceLoadBalancerOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceLoadBalancerGeneratorV1Name: case cmdutil.ServiceLoadBalancerGeneratorV1Name:
@@ -219,12 +260,13 @@ func CreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.C
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateServiceLoadBalancer is the implementation of the create service loadbalancer command
}) func (o *ServiceLoadBalancerOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }
var ( var (
@@ -240,8 +282,19 @@ var (
kubectl create service externalname my-ns --external-name bar.com`)) kubectl create service externalname my-ns --external-name bar.com`))
) )
type ServiceExternalNameOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceExternalName is a macro command for creating an ExternalName service // NewCmdCreateServiceExternalName is a macro command for creating an ExternalName service
func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceExternalNameOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "externalname NAME --external-name external.name [--dry-run]", Use: "externalname NAME --external-name external.name [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -249,13 +302,15 @@ func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra
Long: serviceExternalNameLong, Long: serviceExternalNameLong,
Example: serviceExternalNameExample, Example: serviceExternalNameExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateExternalNameService(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceExternalNameGeneratorV1Name) cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceExternalNameGeneratorV1Name)
addPortFlags(cmd) addPortFlags(cmd)
cmd.Flags().String("external-name", "", i18n.T("External name of service")) cmd.Flags().String("external-name", "", i18n.T("External name of service"))
@@ -263,12 +318,12 @@ func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra
return cmd return cmd
} }
// CreateExternalNameService is the implementation of the create service externalname command func (o *ServiceExternalNameOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateExternalNameService(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceExternalNameGeneratorV1Name: case cmdutil.ServiceExternalNameGeneratorV1Name:
@@ -281,10 +336,11 @@ func CreateExternalNameService(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.C
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateExternalNameService is the implementation of the create service externalname command
}) func (o *ServiceExternalNameOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -36,8 +36,19 @@ var (
kubectl create serviceaccount my-service-account`)) kubectl create serviceaccount my-service-account`))
) )
type ServiceAccountOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceAccount is a macro command to create a new service account // NewCmdCreateServiceAccount is a macro command to create a new service account
func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceAccountOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "serviceaccount NAME [--dry-run]", Use: "serviceaccount NAME [--dry-run]",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@@ -46,24 +57,26 @@ func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comm
Long: serviceAccountLong, Long: serviceAccountLong,
Example: serviceAccountExample, Example: serviceAccountExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceAccount(f, cmdOut, cmd, args) cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Run(f))
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddInclude3rdPartyFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceAccountV1GeneratorName) cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceAccountV1GeneratorName)
return cmd return cmd
} }
// CreateServiceAccount implements the behavior to run the create service account command func (o *ServiceAccountOpts) Complete(cmd *cobra.Command, args []string) error {
func CreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) name, err := NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator kubectl.StructuredGenerator var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceAccountV1GeneratorName: case cmdutil.ServiceAccountV1GeneratorName:
@@ -71,10 +84,11 @@ func CreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comman
default: default:
return errUnsupportedGenerator(cmd, generatorName) return errUnsupportedGenerator(cmd, generatorName)
} }
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name, return o.CreateSubcommandOptions.Complete(cmd, args, generator)
StructuredGenerator: generator, }
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"), // CreateServiceAccount implements the behavior to run the create service account command
}) func (o *ServiceAccountOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
} }

View File

@@ -0,0 +1,81 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package create
import (
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/printers"
)
// PrintFlags composes common printer flag structs
// used across all create commands, and provides a method
// of retrieving a known printer based on flag values provided.
type PrintFlags struct {
JSONYamlPrintFlags *printers.JSONYamlPrintFlags
NamePrintFlags *printers.NamePrintFlags
TemplateFlags *printers.KubeTemplatePrintFlags
OutputFormat *string
}
func (f *PrintFlags) Complete(successTemplate string) error {
return f.NamePrintFlags.Complete(successTemplate)
}
func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) {
outputFormat := ""
if f.OutputFormat != nil {
outputFormat = *f.OutputFormat
}
if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
if p, err := f.TemplateFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
return nil, printers.NoCompatiblePrinterError{Options: f}
}
func (f *PrintFlags) AddFlags(cmd *cobra.Command) {
f.JSONYamlPrintFlags.AddFlags(cmd)
f.NamePrintFlags.AddFlags(cmd)
f.TemplateFlags.AddFlags(cmd)
if f.OutputFormat != nil {
cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].")
}
}
func NewPrintFlags(operation string) *PrintFlags {
outputFormat := ""
return &PrintFlags{
OutputFormat: &outputFormat,
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags(operation),
TemplateFlags: printers.NewKubeTemplatePrintFlags(),
}
}

View File

@@ -130,7 +130,6 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
if o.DryRun { if o.DryRun {
o.PrintFlags.Complete("%s (dry run)") o.PrintFlags.Complete("%s (dry run)")
} }
printer, err := o.PrintFlags.ToPrinter() printer, err := o.PrintFlags.ToPrinter()
if err != nil { if err != nil {
return err return err

View File

@@ -30,6 +30,7 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/printers", importpath = "k8s.io/kubernetes/pkg/printers",
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/scheme:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",

View File

@@ -23,14 +23,18 @@ import (
) )
type NoCompatiblePrinterError struct { type NoCompatiblePrinterError struct {
options interface{} Options interface{}
} }
func (e NoCompatiblePrinterError) Error() string { func (e NoCompatiblePrinterError) Error() string {
return fmt.Sprintf("unable to match a printer suitable for the options specified: %#v", e.options) return fmt.Sprintf("unable to match a printer suitable for the options specified: %#v", e.Options)
} }
func IsNoCompatiblePrinterError(err error) bool { func IsNoCompatiblePrinterError(err error) bool {
if err == nil {
return false
}
_, ok := err.(NoCompatiblePrinterError) _, ok := err.(NoCompatiblePrinterError)
return ok return ok
} }
@@ -45,9 +49,8 @@ type PrintFlags struct {
OutputFormat *string OutputFormat *string
} }
func (f *PrintFlags) Complete(messageTemplate string) error { func (f *PrintFlags) Complete(successTemplate string) error {
f.NamePrintFlags.Operation = fmt.Sprintf(messageTemplate, f.NamePrintFlags.Operation) return f.NamePrintFlags.Complete(successTemplate)
return nil
} }
func (f *PrintFlags) ToPrinter() (ResourcePrinter, error) { func (f *PrintFlags) ToPrinter() (ResourcePrinter, error) {
@@ -56,12 +59,15 @@ func (f *PrintFlags) ToPrinter() (ResourcePrinter, error) {
outputFormat = *f.OutputFormat outputFormat = *f.OutputFormat
} }
p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat) if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
if err == nil { return p, err
return p, nil
} }
return f.NamePrintFlags.ToPrinter(outputFormat) if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
return p, err
}
return nil, NoCompatiblePrinterError{f}
} }
func (f *PrintFlags) AddFlags(cmd *cobra.Command) { func (f *PrintFlags) AddFlags(cmd *cobra.Command) {

View File

@@ -20,6 +20,9 @@ import (
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api/legacyscheme"
kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
// JSONYamlPrintFlags provides default flags necessary for json/yaml printing. // JSONYamlPrintFlags provides default flags necessary for json/yaml printing.
@@ -32,15 +35,21 @@ type JSONYamlPrintFlags struct{}
// Returns false if the specified outputFormat does not match a supported format. // Returns false if the specified outputFormat does not match a supported format.
// Supported Format types can be found in pkg/printers/printers.go // Supported Format types can be found in pkg/printers/printers.go
func (f *JSONYamlPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, error) { func (f *JSONYamlPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, error) {
var printer ResourcePrinter
outputFormat = strings.ToLower(outputFormat) outputFormat = strings.ToLower(outputFormat)
switch outputFormat { switch outputFormat {
case "json": case "json":
return &JSONPrinter{}, nil printer = &JSONPrinter{}
case "yaml": case "yaml":
return &YAMLPrinter{}, nil printer = &YAMLPrinter{}
default: default:
return nil, NoCompatiblePrinterError{f} return nil, NoCompatiblePrinterError{f}
} }
// wrap the printer in a versioning printer that understands when to convert and when not to convert
return NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, kubectlscheme.Versions...), nil
} }
// AddFlags receives a *cobra.Command reference and binds // AddFlags receives a *cobra.Command reference and binds

View File

@@ -37,9 +37,9 @@ type JSONPathPrintFlags struct {
// ToPrinter receives an templateFormat and returns a printer capable of // ToPrinter receives an templateFormat and returns a printer capable of
// handling --template format printing. // handling --template format printing.
// Returns false if the specified templateFormat does not match a template format. // Returns false if the specified templateFormat does not match a template format.
func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, bool, error) { func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, error) {
if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 { if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 {
return nil, false, fmt.Errorf("missing --template value") return nil, NoCompatiblePrinterError{f}
} }
templateValue := "" templateValue := ""
@@ -66,17 +66,17 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter,
} }
if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat { if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat {
return nil, false, nil return nil, NoCompatiblePrinterError{f}
} }
if len(templateValue) == 0 { if len(templateValue) == 0 {
return nil, true, fmt.Errorf("template format specified but no template given") return nil, fmt.Errorf("template format specified but no template given")
} }
if templateFormat == "jsonpath-file" { if templateFormat == "jsonpath-file" {
data, err := ioutil.ReadFile(templateValue) data, err := ioutil.ReadFile(templateValue)
if err != nil { if err != nil {
return nil, true, fmt.Errorf("error reading --template %s, %v\n", templateValue, err) return nil, fmt.Errorf("error reading --template %s, %v\n", templateValue, err)
} }
templateValue = string(data) templateValue = string(data)
@@ -84,7 +84,7 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter,
p, err := NewJSONPathPrinter(templateValue) p, err := NewJSONPathPrinter(templateValue)
if err != nil { if err != nil {
return nil, true, fmt.Errorf("error parsing jsonpath %s, %v\n", templateValue, err) return nil, fmt.Errorf("error parsing jsonpath %s, %v\n", templateValue, err)
} }
allowMissingKeys := true allowMissingKeys := true
@@ -93,7 +93,7 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter,
} }
p.AllowMissingKeys(allowMissingKeys) p.AllowMissingKeys(allowMissingKeys)
return p, true, nil return p, nil
} }
// AddFlags receives a *cobra.Command reference and binds // AddFlags receives a *cobra.Command reference and binds

View File

@@ -103,14 +103,14 @@ func TestPrinterSupportsExpectedJSONPathFormats(t *testing.T) {
TemplateArgument: templateArg, TemplateArgument: templateArg,
} }
p, matched, err := printFlags.ToPrinter(tc.outputFormat) p, err := printFlags.ToPrinter(tc.outputFormat)
if tc.expectNoMatch { if tc.expectNoMatch {
if matched { if !printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) t.Fatalf("expected no printer matches for output format %q", tc.outputFormat)
} }
return return
} }
if !matched { if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) t.Fatalf("expected to match template printer for output format %q", tc.outputFormat)
} }
@@ -183,8 +183,8 @@ func TestJSONPathPrinterDefaultsAllowMissingKeysToTrue(t *testing.T) {
} }
outputFormat := "jsonpath" outputFormat := "jsonpath"
p, matched, err := printFlags.ToPrinter(outputFormat) p, err := printFlags.ToPrinter(outputFormat)
if !matched { if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", outputFormat) t.Fatalf("expected to match template printer for output format %q", outputFormat)
} }
if err != nil { if err != nil {

View File

@@ -29,9 +29,9 @@ type KubeTemplatePrintFlags struct {
TemplateArgument *string TemplateArgument *string
} }
func (f *KubeTemplatePrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, bool, error) { func (f *KubeTemplatePrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, error) {
if p, match, err := f.JSONPathPrintFlags.ToPrinter(outputFormat); match { if p, err := f.JSONPathPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
return p, match, err return p, err
} }
return f.GoTemplatePrintFlags.ToPrinter(outputFormat) return f.GoTemplatePrintFlags.ToPrinter(outputFormat)
} }

View File

@@ -17,6 +17,7 @@ limitations under the License.
package printers package printers
import ( import (
"fmt"
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@@ -37,6 +38,11 @@ type NamePrintFlags struct {
Operation string Operation string
} }
func (f *NamePrintFlags) Complete(successTemplate string) error {
f.Operation = fmt.Sprintf(successTemplate, f.Operation)
return nil
}
// ToPrinter receives an outputFormat and returns a printer capable of // ToPrinter receives an outputFormat and returns a printer capable of
// handling --output=name printing. // handling --output=name printing.
// Returns false if the specified outputFormat does not match a supported format. // Returns false if the specified outputFormat does not match a supported format.

View File

@@ -63,10 +63,7 @@ func GetStandardPrinter(typer runtime.ObjectTyper, encoder runtime.Encoder, deco
}, },
} }
kubeTemplatePrinter, matched, err := kubeTemplateFlags.ToPrinter(format) kubeTemplatePrinter, err := kubeTemplateFlags.ToPrinter(format)
if !matched {
return nil, fmt.Errorf("unable to match a template printer to handle current print options")
}
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -37,9 +37,9 @@ type GoTemplatePrintFlags struct {
// ToPrinter receives an templateFormat and returns a printer capable of // ToPrinter receives an templateFormat and returns a printer capable of
// handling --template format printing. // handling --template format printing.
// Returns false if the specified templateFormat does not match a template format. // Returns false if the specified templateFormat does not match a template format.
func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, bool, error) { func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, error) {
if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 { if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 {
return nil, false, fmt.Errorf("missing --template argument") return nil, NoCompatiblePrinterError{f}
} }
templateValue := "" templateValue := ""
@@ -68,17 +68,17 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter
} }
if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat { if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat {
return nil, false, nil return nil, NoCompatiblePrinterError{f}
} }
if len(templateValue) == 0 { if len(templateValue) == 0 {
return nil, true, fmt.Errorf("template format specified but no template given") return nil, fmt.Errorf("template format specified but no template given")
} }
if templateFormat == "templatefile" || templateFormat == "go-template-file" { if templateFormat == "templatefile" || templateFormat == "go-template-file" {
data, err := ioutil.ReadFile(templateValue) data, err := ioutil.ReadFile(templateValue)
if err != nil { if err != nil {
return nil, true, fmt.Errorf("error reading --template %s, %v\n", templateValue, err) return nil, fmt.Errorf("error reading --template %s, %v\n", templateValue, err)
} }
templateValue = string(data) templateValue = string(data)
@@ -86,7 +86,7 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter
p, err := NewGoTemplatePrinter([]byte(templateValue)) p, err := NewGoTemplatePrinter([]byte(templateValue))
if err != nil { if err != nil {
return nil, true, fmt.Errorf("error parsing template %s, %v\n", templateValue, err) return nil, fmt.Errorf("error parsing template %s, %v\n", templateValue, err)
} }
allowMissingKeys := true allowMissingKeys := true
@@ -95,7 +95,7 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter
} }
p.AllowMissingKeys(allowMissingKeys) p.AllowMissingKeys(allowMissingKeys)
return p, true, nil return p, nil
} }
// AddFlags receives a *cobra.Command reference and binds // AddFlags receives a *cobra.Command reference and binds

View File

@@ -103,14 +103,14 @@ func TestPrinterSupportsExpectedTemplateFormats(t *testing.T) {
TemplateArgument: templateArg, TemplateArgument: templateArg,
} }
p, matched, err := printFlags.ToPrinter(tc.outputFormat) p, err := printFlags.ToPrinter(tc.outputFormat)
if tc.expectNoMatch { if tc.expectNoMatch {
if matched { if !printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) t.Fatalf("expected no printer matches for output format %q", tc.outputFormat)
} }
return return
} }
if !matched { if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) t.Fatalf("expected to match template printer for output format %q", tc.outputFormat)
} }
@@ -177,8 +177,8 @@ func TestTemplatePrinterDefaultsAllowMissingKeysToTrue(t *testing.T) {
} }
outputFormat := "template" outputFormat := "template"
p, matched, err := printFlags.ToPrinter(outputFormat) p, err := printFlags.ToPrinter(outputFormat)
if !matched { if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", outputFormat) t.Fatalf("expected to match template printer for output format %q", outputFormat)
} }
if err != nil { if err != nil {