Merge pull request #62181 from juanvallejo/jvallejo/wire-print-flags-create-cmds

Automatic merge from submit-queue (batch tested with PRs 61306, 60270, 62496, 62181, 62234). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

wire printflags through create commands

**Release note**:
```release-note
NONE
```

~~Depends on https://github.com/kubernetes/kubernetes/pull/62139~~
~~Depends on https://github.com/kubernetes/kubernetes/pull/62341~~

Begins wiring PrintFlags through create subcommands.
Opening now to begin gathering feedback.

cc @soltysh @deads2k
This commit is contained in:
Kubernetes Submit Queue 2018-04-13 15:03:13 -07:00 committed by GitHub
commit 1ef0153e02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 762 additions and 295 deletions

View File

@ -18,6 +18,7 @@ go_library(
"create_secret.go",
"create_service.go",
"create_serviceaccount.go",
"flags.go",
],
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/create",
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/resource:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library",
"//pkg/printers: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/v1beta1:go_default_library",

View File

@ -28,6 +28,7 @@ import (
"net/url"
"k8s.io/apimachinery/pkg/api/meta"
kruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
@ -38,6 +39,11 @@ import (
)
type CreateOptions struct {
PrintFlags *PrintFlags
PrintObj func(obj kruntime.Object) error
DryRun bool
FilenameOptions resource.FilenameOptions
Selector string
EditBeforeCreate bool
@ -65,6 +71,8 @@ var (
func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
options := &CreateOptions{
PrintFlags: NewPrintFlags("created"),
Out: out,
ErrOut: errOut,
}
@ -81,6 +89,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
defaultRunFunc(cmd, args)
return
}
cmdutil.CheckErr(options.Complete(cmd))
cmdutil.CheckErr(options.ValidateArgs(cmd, args))
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)
cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmd.Flags().BoolVar(&options.EditBeforeCreate, "edit", options.EditBeforeCreate, "Edit the API resource before creating")
cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows",
"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().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
cmd.AddCommand(NewCmdCreateNamespace(f, out))
cmd.AddCommand(NewCmdCreateQuota(f, out))
@ -150,6 +160,24 @@ func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error {
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 {
// raw only makes sense for a single file resource multiple objects aren't likely to do what you want.
// the validator enforces this, so
@ -184,9 +212,6 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
return err
}
dryRun := cmdutil.GetDryRunFlag(cmd)
output := cmdutil.GetFlagString(cmd, "output")
count := 0
err = r.Visit(func(info *resource.Info, err error) error {
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 {
return cmdutil.AddSourceToErr("creating", info.Source, err)
}
@ -210,13 +235,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
count++
shortOutput := output == "name"
if len(output) > 0 && !shortOutput {
return cmdutil.PrintObject(cmd, info.Object, o.Out)
}
cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, dryRun, "created")
return nil
return o.PrintObj(info.Object)
})
if err != nil {
return err
@ -295,17 +314,52 @@ func NameFromCommandArgs(cmd *cobra.Command, args []string) (string, error) {
// CreateSubcommandOptions is an options struct to support create subcommands
type CreateSubcommandOptions struct {
// PrintFlags holds options necessary for obtaining a printer
PrintFlags *PrintFlags
// Name of resource being created
Name string
// StructuredGenerator is the resource generator for the object being created
StructuredGenerator kubectl.StructuredGenerator
// DryRun is true if the command should be simulated but not run against the server
DryRun bool
OutputFormat string
DryRun bool
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
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()
if err != nil {
return err
@ -338,25 +392,22 @@ func RunCreateSubcommand(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, o
if err != nil {
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
}
obj = info.Object
obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object)
if err != nil {
return err
}
// ensure we pass a versioned object to the printer
obj = info.AsVersioned()
} else {
if meta, err := meta.Accessor(obj); err == nil && nsOverriden {
meta.SetNamespace(namespace)
}
}
if useShortOutput := options.OutputFormat == "name"; useShortOutput || len(options.OutputFormat) == 0 {
cmdutil.PrintSuccess(useShortOutput, out, obj, options.DryRun, "created")
return nil
}
return cmdutil.PrintObject(cmd, obj, out)
return options.PrintObj(obj)
}

View File

@ -62,7 +62,8 @@ type CreateClusterRoleOptions struct {
func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
c := &CreateClusterRoleOptions{
CreateRoleOptions: &CreateRoleOptions{
Out: cmdOut,
PrintFlags: NewPrintFlags("created"),
Out: cmdOut,
},
}
cmd := &cobra.Command{
@ -77,9 +78,11 @@ func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command
cmdutil.CheckErr(c.RunCreateRole())
},
}
c.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(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.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 {
cmdutil.PrintSuccess(useShortOutput, c.Out, clusterRole, c.DryRun, "created")
return nil
}
return c.PrintObject(clusterRole)
return c.PrintObj(clusterRole)
}

View File

@ -36,8 +36,19 @@ var (
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.
func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ClusterRoleBindingOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]",
DisableFlagsInUseLine: true,
@ -45,13 +56,15 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.
Long: clusterRoleBindingLong,
Example: clusterRoleBindingExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateClusterRoleBinding(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ClusterRoleBindingV1GeneratorName)
cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole this ClusterRoleBinding should reference"))
cmd.MarkFlagCustom("clusterrole", "__kubectl_get_resource_clusterrole")
@ -61,12 +74,12 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.
return cmd
}
// CreateClusterRoleBinding is the implementation of the create clusterrolebinding command.
func CreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *ClusterRoleBindingOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ClusterRoleBindingV1GeneratorName:
@ -80,10 +93,11 @@ func CreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Co
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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`))
)
type ConfigMapOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// ConfigMap is a command to ease creating ConfigMaps.
func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ConfigMapOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]",
DisableFlagsInUseLine: true,
@ -67,13 +78,15 @@ func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: configMapLong,
Example: configMapExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateConfigMap(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
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().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
}
// CreateConfigMap is the implementation of the create configmap command.
func CreateConfigMap(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *ConfigMapOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ConfigMapV1GeneratorName:
@ -101,10 +114,11 @@ func CreateConfigMap(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, ar
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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`))
)
type DeploymentOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateDeployment is a macro command to create a new deployment.
// This command is better known to users as `kubectl create deployment`.
// Note that this command overlaps significantly with the `kubectl run` 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{
Use: "deployment NAME --image=image [--dry-run]",
DisableFlagsInUseLine: true,
@ -48,13 +60,15 @@ func NewCmdCreateDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.
Long: deploymentLong,
Example: deploymentExample,
Run: func(cmd *cobra.Command, args []string) {
err := createDeployment(f, cmdOut, cmdErr, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(f, cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, "")
cmd.Flags().StringSlice("image", []string{}, "Image name to run.")
cmd.MarkFlagRequired("image")
@ -102,14 +116,8 @@ func generatorFromName(
return nil, false
}
// createDeployment
// 1. Reads user config values from Cobra.
// 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)
func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
@ -123,27 +131,30 @@ func createDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer,
if len(generatorName) == 0 {
generatorName = cmdutil.DeploymentBasicAppsV1GeneratorName
generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), cmdErr)
generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), o.CreateSubcommandOptions.CmdErr)
if err != nil {
return err
}
if generatorNameTemp != generatorName {
cmdutil.Warning(cmdErr, generatorName, generatorNameTemp)
cmdutil.Warning(o.CreateSubcommandOptions.CmdErr, generatorName, generatorNameTemp)
} else {
generatorName = generatorNameTemp
}
}
imageNames := cmdutil.GetFlagStringSlice(cmd, "image")
generator, ok := generatorFromName(generatorName, imageNames, deploymentName)
generator, ok := generatorFromName(generatorName, imageNames, name)
if !ok {
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: deploymentName,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// createDeployment
// 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()
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{
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(&bytes.Buffer{}),
Body: ioutil.NopCloser(bytes.NewBuffer([]byte(fakeDiscovery))),
}, nil
}),
}
@ -137,9 +137,23 @@ func TestCreateDeploymentNoImage(t *testing.T) {
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdCreateDeployment(tf, buf, buf)
cmd.Flags().Set("dry-run", "true")
errBuff := bytes.NewBuffer([]byte{})
cmd := NewCmdCreateDeployment(tf, buf, errBuff)
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")
}

View File

@ -25,6 +25,7 @@ import (
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
@ -42,6 +43,10 @@ var (
)
type CreateJobOptions struct {
PrintFlags *PrintFlags
PrintObj func(obj runtime.Object) error
Name string
From string
@ -57,7 +62,8 @@ type CreateJobOptions struct {
// NewCmdCreateJob is a command to ease creating Jobs from CronJobs.
func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
c := &CreateJobOptions{
Out: cmdOut,
PrintFlags: NewPrintFlags("created"),
Out: cmdOut,
}
cmd := &cobra.Command{
Use: "job NAME [--from=CRONJOB]",
@ -69,9 +75,11 @@ func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmdutil.CheckErr(c.RunCreateJob())
},
}
c.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddDryRunFlag(cmd)
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.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
}
@ -150,10 +170,5 @@ func (c *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error {
}
}
if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 {
cmdutil.PrintSuccess(useShortOutput, c.Out, job, c.DryRun, "created")
return nil
}
return cmdutil.PrintObject(c.Cmd, job, c.Out)
return c.PrintObj(job)
}

View File

@ -84,13 +84,24 @@ func TestCreateJobFromCronJob(t *testing.T) {
f := cmdtesting.NewTestFactory()
defer f.Cleanup()
printFlags := NewPrintFlags("created")
buf := bytes.NewBuffer([]byte{})
cmdOptions := &CreateJobOptions{
Name: testJobName,
Namespace: testNamespaceName,
Client: clientset.BatchV1(),
Out: buf,
Cmd: NewCmdCreateJob(f, buf),
PrintFlags: printFlags,
Name: testJobName,
Namespace: testNamespaceName,
Client: clientset.BatchV1(),
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)

View File

@ -36,8 +36,19 @@ var (
kubectl create namespace my-namespace`))
)
type NamespaceOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateNamespace is a macro command to create a new namespace
func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &NamespaceOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "namespace NAME [--dry-run]",
DisableFlagsInUseLine: true,
@ -46,24 +57,26 @@ func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: namespaceLong,
Example: namespaceExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateNamespace(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName)
return cmd
}
// CreateNamespace implements the behavior to run the create namespace command
func CreateNamespace(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *NamespaceOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.NamespaceV1GeneratorName:
@ -71,10 +84,11 @@ func CreateNamespace(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, ar
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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%`))
)
type PodDisruptionBudgetOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreatePodDisruptionBudget is a macro command to create a new pod disruption budget.
func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &PodDisruptionBudgetOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "poddisruptionbudget NAME --selector=SELECTOR --min-available=N [--dry-run]",
DisableFlagsInUseLine: true,
@ -51,14 +62,15 @@ func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra
Long: pdbLong,
Example: pdbExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreatePodDisruptionBudget(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.PodDisruptionBudgetV2GeneratorName)
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
}
// CreatePodDisruptionBudget implements the behavior to run the create pdb command.
func CreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *PodDisruptionBudgetOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.PodDisruptionBudgetV1GeneratorName:
@ -91,10 +103,11 @@ func CreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.C
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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"
buf := bytes.NewBuffer([]byte{})
outputFormat := "name"
cmd := NewCmdCreatePodDisruptionBudget(tf, buf)
cmd.Flags().Set("min-available", "1")
cmd.Flags().Set("selector", "app=rails")
cmd.Flags().Set("dry-run", "true")
cmd.Flags().Set("output", "name")
CreatePodDisruptionBudget(tf, buf, cmd, []string{pdbName})
cmd.Flags().Set("output", outputFormat)
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"
if buf.String() != expectedOutput {
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"`))
)
type PriorityClassOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreatePriorityClass is a macro command to create a new priorityClass.
func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &PriorityClassOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run]",
DisableFlagsInUseLine: true,
@ -49,13 +60,15 @@ func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma
Long: pcLong,
Example: pcExample,
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.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.PriorityClassV1Alpha1GeneratorName)
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
}
// CreatePriorityClass implements the behavior to run the create priorityClass command.
func CreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *PriorityClassOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.PriorityClassV1Alpha1GeneratorName:
@ -82,10 +95,11 @@ func CreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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{}
buf := bytes.NewBuffer([]byte{})
outputFormat := "name"
cmd := NewCmdCreatePriorityClass(tf, buf)
cmd.Flags().Set("value", "1000")
cmd.Flags().Set("global-default", "true")
cmd.Flags().Set("description", "my priority")
cmd.Flags().Set("dry-run", "true")
cmd.Flags().Set("output", "name")
CreatePriorityClass(tf, buf, cmd, []string{pcName})
cmd.Flags().Set("output", outputFormat)
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"
if buf.String() != expectedOutput {
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`))
)
type QuotaOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateQuota is a macro command to create a new quota
func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &QuotaOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "quota NAME [--hard=key1=value1,key2=value2] [--scopes=Scope1,Scope2] [--dry-run=bool]",
DisableFlagsInUseLine: true,
@ -49,26 +60,27 @@ func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: quotaLong,
Example: quotaExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateQuota(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
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("scopes", "", i18n.T("A comma-delimited set of quota scopes that must all match each object tracked by the quota."))
return cmd
}
// CreateQuota implements the behavior to run the create quota command
func CreateQuota(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *QuotaOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ResourceQuotaV1GeneratorName:
@ -80,10 +92,11 @@ func CreateQuota(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args [
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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 {
PrintFlags *PrintFlags
Name string
Verbs []string
Resources []ResourceOptions
@ -111,12 +113,14 @@ type CreateRoleOptions struct {
Client clientgorbacv1.RbacV1Interface
Mapper meta.RESTMapper
Out io.Writer
PrintObject func(obj runtime.Object) error
PrintObj func(obj runtime.Object) error
}
// Role is a command to ease creating Roles.
func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
c := &CreateRoleOptions{
PrintFlags: NewPrintFlags("created"),
Out: cmdOut,
}
cmd := &cobra.Command{
@ -131,9 +135,11 @@ func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmdutil.CheckErr(c.RunCreateRole())
},
}
c.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddDryRunFlag(cmd)
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")
@ -198,13 +204,20 @@ func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
c.DryRun = cmdutil.GetDryRunFlag(cmd)
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 {
return err
}
c.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, c.Out)
}
c.PrintObject = func(obj runtime.Object) error {
return cmdutil.PrintObject(cmd, obj, c.Out)
c.Namespace, _, err = f.DefaultNamespace()
if err != nil {
return err
}
clientset, err := f.KubernetesClientSet()
@ -292,12 +305,7 @@ func (c *CreateRoleOptions) RunCreateRole() error {
}
}
if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 {
cmdutil.PrintSuccess(useShortOutput, c.Out, role, c.DryRun, "created")
return nil
}
return c.PrintObject(role)
return c.PrintObj(role)
}
func arrayContains(s []string, e string) bool {

View File

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

View File

@ -36,8 +36,19 @@ var (
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.
func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &RoleBindingOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]",
DisableFlagsInUseLine: true,
@ -45,13 +56,15 @@ func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command
Long: roleBindingLong,
Example: roleBindingExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateRoleBinding(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.RoleBindingV1GeneratorName)
cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole 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
}
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)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.RoleBindingV1GeneratorName:
@ -80,10 +94,10 @@ func CreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command,
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
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`))
)
type SecretGenericOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values
func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &SecretGenericOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]",
DisableFlagsInUseLine: true,
@ -82,13 +93,15 @@ func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma
Long: secretLong,
Example: secretExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretGeneric(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
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().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
}
// CreateSecretGeneric is the implementation of the create secret generic command
func CreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *SecretGenericOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.SecretV1GeneratorName:
@ -118,12 +131,13 @@ func CreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// CreateSecretGeneric is the implementation of the create secret generic command
func (o *SecretGenericOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
}
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`))
)
type SecretDockerRegistryOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries
func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &SecretDockerRegistryOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
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]",
DisableFlagsInUseLine: true,
@ -156,13 +181,15 @@ func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobr
Long: secretForDockerRegistryLong,
Example: secretForDockerRegistryExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretDockerRegistry(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForDockerRegistryV1GeneratorName)
cmd.Flags().String("docker-username", "", i18n.T("Username for Docker registry authentication"))
cmd.MarkFlagRequired("docker-username")
@ -177,12 +204,12 @@ func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobr
return cmd
}
// CreateSecretDockerRegistry is the implementation of the create secret docker-registry command
func CreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *SecretDockerRegistryOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
fromFileFlag := cmdutil.GetFlagStringSlice(cmd, "from-file")
if len(fromFileFlag) == 0 {
requiredFlags := []string{"docker-username", "docker-password", "docker-server"}
@ -208,12 +235,13 @@ func CreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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 (
@ -228,8 +256,19 @@ var (
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
func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &SecretTLSOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]",
DisableFlagsInUseLine: true,
@ -237,13 +276,15 @@ func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Long: secretForTLSLong,
Example: secretForTLSExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretTLS(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForTLSV1GeneratorName)
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."))
@ -251,12 +292,12 @@ func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
return cmd
}
// CreateSecretTLS is the implementation of the create secret tls command
func CreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *SecretTLSOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
requiredFlags := []string{"cert", "key"}
for _, requiredFlag := range requiredFlags {
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:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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>'.")
}
type ServiceClusterIPOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceClusterIP is a command to create a ClusterIP service
func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceClusterIPOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "clusterip NAME [--tcp=<port>:<targetPort>] [--dry-run]",
DisableFlagsInUseLine: true,
@ -70,13 +81,15 @@ func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Co
Long: serviceClusterIPLong,
Example: serviceClusterIPExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceClusterIP(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceClusterIPGeneratorV1Name)
addPortFlags(cmd)
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)
}
// CreateServiceClusterIP is the implementation of the create service clusterip command
func CreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *ServiceClusterIPOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceClusterIPGeneratorV1Name:
@ -105,12 +118,13 @@ func CreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comm
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// CreateServiceClusterIP is the implementation of the create service clusterip command
func (o *ServiceClusterIPOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
}
var (
@ -122,8 +136,19 @@ var (
kubectl create service nodeport my-ns --tcp=5678:8080`))
)
type ServiceNodePortOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceNodePort is a macro command for creating a NodePort service
func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceNodePortOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]",
DisableFlagsInUseLine: true,
@ -131,25 +156,27 @@ func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Com
Long: serviceNodePortLong,
Example: serviceNodePortExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceNodePort(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceNodePortGeneratorV1Name)
cmd.Flags().Int("node-port", 0, "Port used to expose the service on each node in a cluster.")
addPortFlags(cmd)
return cmd
}
// CreateServiceNodePort is the implementation of the create service nodeport command
func CreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *ServiceNodePortOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceNodePortGeneratorV1Name:
@ -163,12 +190,13 @@ func CreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comma
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// CreateServiceNodePort is the implementation of the create service nodeport command
func (o *ServiceNodePortOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
}
var (
@ -180,8 +208,19 @@ var (
kubectl create service loadbalancer my-lbs --tcp=5678:8080`))
)
type ServiceLoadBalancerOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service
func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceLoadBalancerOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]",
DisableFlagsInUseLine: true,
@ -189,24 +228,26 @@ func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra
Long: serviceLoadBalancerLong,
Example: serviceLoadBalancerExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceLoadBalancer(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceLoadBalancerGeneratorV1Name)
addPortFlags(cmd)
return cmd
}
// CreateServiceLoadBalancer is the implementation of the create service loadbalancer command
func CreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *ServiceLoadBalancerOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceLoadBalancerGeneratorV1Name:
@ -219,12 +260,13 @@ func CreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.C
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// CreateServiceLoadBalancer is the implementation of the create service loadbalancer command
func (o *ServiceLoadBalancerOpts) Run(f cmdutil.Factory) error {
return RunCreateSubcommand(f, o.CreateSubcommandOptions)
}
var (
@ -240,8 +282,19 @@ var (
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
func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceExternalNameOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "externalname NAME --external-name external.name [--dry-run]",
DisableFlagsInUseLine: true,
@ -249,13 +302,15 @@ func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra
Long: serviceExternalNameLong,
Example: serviceExternalNameExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateExternalNameService(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceExternalNameGeneratorV1Name)
addPortFlags(cmd)
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
}
// CreateExternalNameService is the implementation of the create service externalname command
func CreateExternalNameService(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *ServiceExternalNameOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceExternalNameGeneratorV1Name:
@ -281,10 +336,11 @@ func CreateExternalNameService(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.C
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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`))
)
type ServiceAccountOpts struct {
CreateSubcommandOptions *CreateSubcommandOptions
}
// NewCmdCreateServiceAccount is a macro command to create a new service account
func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
options := &ServiceAccountOpts{
CreateSubcommandOptions: &CreateSubcommandOptions{
PrintFlags: NewPrintFlags("created"),
CmdOut: cmdOut,
},
}
cmd := &cobra.Command{
Use: "serviceaccount NAME [--dry-run]",
DisableFlagsInUseLine: true,
@ -46,24 +57,26 @@ func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comm
Long: serviceAccountLong,
Example: serviceAccountExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateServiceAccount(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
cmdutil.CheckErr(options.Complete(cmd, args))
cmdutil.CheckErr(options.Run(f))
},
}
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceAccountV1GeneratorName)
return cmd
}
// CreateServiceAccount implements the behavior to run the create service account command
func CreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
func (o *ServiceAccountOpts) Complete(cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.ServiceAccountV1GeneratorName:
@ -71,10 +84,11 @@ func CreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comman
default:
return errUnsupportedGenerator(cmd, generatorName)
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetDryRunFlag(cmd),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
return o.CreateSubcommandOptions.Complete(cmd, args, generator)
}
// 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 {
o.PrintFlags.Complete("%s (dry run)")
}
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err

View File

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

View File

@ -23,14 +23,18 @@ import (
)
type NoCompatiblePrinterError struct {
options interface{}
Options interface{}
}
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 {
if err == nil {
return false
}
_, ok := err.(NoCompatiblePrinterError)
return ok
}
@ -45,9 +49,8 @@ type PrintFlags struct {
OutputFormat *string
}
func (f *PrintFlags) Complete(messageTemplate string) error {
f.NamePrintFlags.Operation = fmt.Sprintf(messageTemplate, f.NamePrintFlags.Operation)
return nil
func (f *PrintFlags) Complete(successTemplate string) error {
return f.NamePrintFlags.Complete(successTemplate)
}
func (f *PrintFlags) ToPrinter() (ResourcePrinter, error) {
@ -56,12 +59,15 @@ func (f *PrintFlags) ToPrinter() (ResourcePrinter, error) {
outputFormat = *f.OutputFormat
}
p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat)
if err == nil {
return p, nil
if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
return p, err
}
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) {

View File

@ -20,6 +20,9 @@ import (
"strings"
"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.
@ -32,15 +35,21 @@ type JSONYamlPrintFlags struct{}
// Returns false if the specified outputFormat does not match a supported format.
// Supported Format types can be found in pkg/printers/printers.go
func (f *JSONYamlPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, error) {
var printer ResourcePrinter
outputFormat = strings.ToLower(outputFormat)
switch outputFormat {
case "json":
return &JSONPrinter{}, nil
printer = &JSONPrinter{}
case "yaml":
return &YAMLPrinter{}, nil
printer = &YAMLPrinter{}
default:
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

View File

@ -37,9 +37,9 @@ type JSONPathPrintFlags struct {
// ToPrinter receives an templateFormat and returns a printer capable of
// handling --template format printing.
// 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 {
return nil, false, fmt.Errorf("missing --template value")
return nil, NoCompatiblePrinterError{f}
}
templateValue := ""
@ -66,17 +66,17 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter,
}
if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat {
return nil, false, nil
return nil, NoCompatiblePrinterError{f}
}
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" {
data, err := ioutil.ReadFile(templateValue)
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)
@ -84,7 +84,7 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter,
p, err := NewJSONPathPrinter(templateValue)
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
@ -93,7 +93,7 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter,
}
p.AllowMissingKeys(allowMissingKeys)
return p, true, nil
return p, nil
}
// AddFlags receives a *cobra.Command reference and binds

View File

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

View File

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

View File

@ -17,6 +17,7 @@ limitations under the License.
package printers
import (
"fmt"
"strings"
"github.com/spf13/cobra"
@ -37,6 +38,11 @@ type NamePrintFlags struct {
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
// handling --output=name printing.
// 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)
if !matched {
return nil, fmt.Errorf("unable to match a template printer to handle current print options")
}
kubeTemplatePrinter, err := kubeTemplateFlags.ToPrinter(format)
if err != nil {
return nil, err
}

View File

@ -37,9 +37,9 @@ type GoTemplatePrintFlags struct {
// ToPrinter receives an templateFormat and returns a printer capable of
// handling --template format printing.
// 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 {
return nil, false, fmt.Errorf("missing --template argument")
return nil, NoCompatiblePrinterError{f}
}
templateValue := ""
@ -68,17 +68,17 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter
}
if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat {
return nil, false, nil
return nil, NoCompatiblePrinterError{f}
}
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" {
data, err := ioutil.ReadFile(templateValue)
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)
@ -86,7 +86,7 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter
p, err := NewGoTemplatePrinter([]byte(templateValue))
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
@ -95,7 +95,7 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter
}
p.AllowMissingKeys(allowMissingKeys)
return p, true, nil
return p, nil
}
// AddFlags receives a *cobra.Command reference and binds

View File

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