Merge pull request #30815 from ymqytw/refactoring

Automatic merge from submit-queue

Fixes #30562: Refactor kubectl command options to use common struct for common file params

Fixes #30562 : Refactor common go struct options in pkg/kubectl/cmd/*.go.
@pwittrock
This commit is contained in:
Kubernetes Submit Queue 2016-09-16 19:48:22 -07:00 committed by GitHub
commit 051ee17094
28 changed files with 182 additions and 291 deletions

View File

@ -36,11 +36,12 @@ import (
// AnnotateOptions have the data required to perform the annotate operation
type AnnotateOptions struct {
resource.FilenameOptions
resources []string
newAnnotations map[string]string
removeAnnotations []string
builder *resource.Builder
filenames []string
selector string
overwrite bool
@ -53,8 +54,6 @@ type AnnotateOptions struct {
f *cmdutil.Factory
out io.Writer
cmd *cobra.Command
recursive bool
}
var (
@ -128,9 +127,8 @@ func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().BoolVar(&options.overwrite, "overwrite", false, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.")
cmd.Flags().BoolVar(&options.all, "all", false, "select all resources in the namespace of the specified resource types")
cmd.Flags().StringVar(&options.resourceVersion, "resource-version", "", "If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")
usage := "Filename, directory, or URL to a file identifying the resource to update the annotation"
kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.recursive)
usage := "identifying the resource to update the annotation"
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -150,7 +148,7 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra
return err
}
o.resources = resources
if len(o.resources) < 1 && len(o.filenames) == 0 {
if len(o.resources) < 1 && cmdutil.IsFilenameEmpty(o.Filenames) {
return fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>")
}
if len(annotationArgs) < 1 {
@ -168,7 +166,7 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra
o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().
FilenameParam(enforceNamespace, o.recursive, o.filenames...).
FilenameParam(enforceNamespace, &o.FilenameOptions).
SelectorParam(o.selector).
ResourceTypeOrNameArgs(o.all, o.resources...).
Flatten().

View File

@ -504,7 +504,7 @@ func TestAnnotateObjectFromFile(t *testing.T) {
cmd := NewCmdAnnotate(f, buf)
cmd.SetOutput(buf)
options := &AnnotateOptions{}
options.filenames = []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"}
options.Filenames = []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"}
args := []string{"a=b", "c-"}
if err := options.Complete(f, buf, cmd, args); err != nil {
t.Fatalf("unexpected error: %v", err)

View File

@ -35,13 +35,6 @@ import (
"k8s.io/kubernetes/pkg/util/strategicpatch"
)
// ApplyOptions stores cmd.Flag values for apply. As new fields are added,
// add them here instead of referencing the cmd.Flags()
type ApplyOptions struct {
Filenames []string
Recursive bool
}
const (
// maxPatchRetry is the maximum number of conflicts retry for during a patch operation before returning failure
maxPatchRetry = 5
@ -68,7 +61,7 @@ var (
)
func NewCmdApply(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &ApplyOptions{}
options := &resource.FilenameOptions{}
cmd := &cobra.Command{
Use: "apply -f FILENAME",
@ -82,12 +75,11 @@ func NewCmdApply(f *cmdutil.Factory, out io.Writer) *cobra.Command {
},
}
usage := "Filename, directory, or URL to file that contains the configuration to apply"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
usage := "that contains the configuration to apply"
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmd.MarkFlagRequired("filename")
cmd.Flags().Bool("overwrite", true, "Automatically resolve conflicts between the modified and live configuration by using values from the modified configuration")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
@ -102,7 +94,7 @@ func validateArgs(cmd *cobra.Command, args []string) error {
return nil
}
func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *ApplyOptions) error {
func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *resource.FilenameOptions) error {
shortOutput := cmdutil.GetFlagString(cmd, "output") == "name"
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir"))
if err != nil {
@ -119,7 +111,7 @@ func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *Ap
Schema(schema).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
Flatten().
Do()
err = r.Err()

View File

@ -30,13 +30,6 @@ import (
"github.com/spf13/cobra"
)
// AutoscaleOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type AutoscaleOptions struct {
Filenames []string
Recursive bool
}
var (
autoscaleLong = dedent.Dedent(`
Creates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.
@ -53,7 +46,7 @@ var (
)
func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &AutoscaleOptions{}
options := &resource.FilenameOptions{}
validArgs := []string{"deployment", "replicaset", "replicationcontroller"}
argAliases := kubectl.ResourceAliases(validArgs)
@ -78,16 +71,15 @@ func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Int("cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used."))
cmd.Flags().String("name", "", "The name for the newly created object. If not specified, the name of the input resource will be used.")
cmdutil.AddDryRunFlag(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to autoscale."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "identifying the resource to autoscale."
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *AutoscaleOptions) error {
func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
namespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
return err
@ -102,7 +94,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(false, args...).
Flatten().
Do()

View File

@ -78,9 +78,8 @@ func NewCmdConvert(f *cmdutil.Factory, out io.Writer) *cobra.Command {
},
}
usage := "Filename, directory, or URL to file to need to get converted."
kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.recursive)
usage := "to need to get converted."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
@ -91,17 +90,16 @@ func NewCmdConvert(f *cmdutil.Factory, out io.Writer) *cobra.Command {
// ConvertOptions have the data required to perform the convert operation
type ConvertOptions struct {
builder *resource.Builder
filenames []string
local bool
resource.FilenameOptions
builder *resource.Builder
local bool
encoder runtime.Encoder
out io.Writer
printer kubectl.ResourcePrinter
outputVersion unversioned.GroupVersion
recursive bool
}
// Complete collects information required to run Convert command from command line.
@ -135,7 +133,7 @@ func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.
}
o.builder = o.builder.NamespaceParam(cmdNamespace).
ContinueOnError().
FilenameParam(false, o.recursive, o.filenames...).
FilenameParam(false, &o.FilenameOptions).
Flatten()
// build the printer

View File

@ -30,13 +30,6 @@ import (
"k8s.io/kubernetes/pkg/runtime"
)
// CreateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type CreateOptions struct {
Filenames []string
Recursive bool
}
var (
create_long = dedent.Dedent(`
Create a resource by filename or stdin.
@ -51,7 +44,7 @@ var (
)
func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &CreateOptions{}
options := &resource.FilenameOptions{}
cmd := &cobra.Command{
Use: "create -f FILENAME",
@ -59,7 +52,7 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
Long: create_long,
Example: create_example,
Run: func(cmd *cobra.Command, args []string) {
if len(options.Filenames) == 0 {
if cmdutil.IsFilenameEmpty(options.Filenames) {
cmd.Help()
return
}
@ -69,11 +62,10 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
},
}
usage := "Filename, directory, or URL to file to use to create the resource"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
usage := "to use to create the resource"
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
@ -97,7 +89,7 @@ func ValidateArgs(cmd *cobra.Command, args []string) error {
return nil
}
func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateOptions) error {
func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *resource.FilenameOptions) error {
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir"))
if err != nil {
return err
@ -116,7 +108,7 @@ func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *C
Schema(schema).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
Flatten().
Do()
err = r.Err()

View File

@ -32,13 +32,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/resource"
)
// DeleteOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type DeleteOptions struct {
Filenames []string
Recursive bool
}
var (
delete_long = dedent.Dedent(`
Delete resources by filenames, stdin, resources and names, or by resources and label selector.
@ -74,7 +67,7 @@ var (
)
func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &DeleteOptions{}
options := &resource.FilenameOptions{}
// retrieve a list of handled resources from printer as valid args
validArgs, argAliases := []string{}, []string{}
@ -101,9 +94,8 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
ValidArgs: validArgs,
ArgAliases: argAliases,
}
usage := "Filename, directory, or URL to a file containing the resource to delete."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "containing the resource to delete."
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.")
cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.")
@ -116,7 +108,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
return cmd
}
func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DeleteOptions) error {
func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
return err
@ -126,7 +118,7 @@ func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
SelectAllParam(deleteAll).
ResourceTypeOrNameArgs(false, args...).RequireObject(false).

View File

@ -28,6 +28,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/unversioned/fake"
"k8s.io/kubernetes/pkg/kubectl/resource"
)
func TestDeleteObjectByTuple(t *testing.T) {
@ -145,9 +146,8 @@ func TestDeleteObjectNotFound(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdDelete(f, buf)
options := &DeleteOptions{
Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"},
}
options := &resource.FilenameOptions{}
options.Filenames = []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}
cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("output", "name")
err := RunDelete(f, buf, cmd, []string{}, options)
@ -222,7 +222,7 @@ func TestDeleteAllNotFound(t *testing.T) {
cmd.Flags().Set("ignore-not-found", "false")
cmd.Flags().Set("output", "name")
err := RunDelete(f, buf, cmd, []string{"services"}, &DeleteOptions{})
err := RunDelete(f, buf, cmd, []string{"services"}, &resource.FilenameOptions{})
if err == nil || !errors.IsNotFound(err) {
t.Errorf("unexpected error: expected NotFound, got %v", err)
}
@ -325,9 +325,8 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdDelete(f, buf)
options := &DeleteOptions{
Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml", "../../../examples/guestbook/frontend-service.yaml"},
}
options := &resource.FilenameOptions{}
options.Filenames = []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml", "../../../examples/guestbook/frontend-service.yaml"}
cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("output", "name")
err := RunDelete(f, buf, cmd, []string{}, options)
@ -486,7 +485,7 @@ func TestResourceErrors(t *testing.T) {
for k, v := range testCase.flags {
cmd.Flags().Set(k, v)
}
err := RunDelete(f, buf, cmd, testCase.args, &DeleteOptions{})
err := RunDelete(f, buf, cmd, testCase.args, &resource.FilenameOptions{})
if !testCase.errFn(err) {
t.Errorf("%s: unexpected error: %v", k, err)
continue

View File

@ -33,13 +33,6 @@ import (
utilerrors "k8s.io/kubernetes/pkg/util/errors"
)
// DescribeOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type DescribeOptions struct {
Filenames []string
Recursive bool
}
var (
describe_long = dedent.Dedent(`
Show details of a specific resource or group of resources.
@ -75,7 +68,7 @@ var (
)
func NewCmdDescribe(f *cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command {
options := &DescribeOptions{}
options := &resource.FilenameOptions{}
describerSettings := &kubectl.DescriberSettings{}
validArgs := kubectl.DescribableResources()
@ -93,9 +86,8 @@ func NewCmdDescribe(f *cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command {
ValidArgs: validArgs,
ArgAliases: argAliases,
}
usage := "Filename, directory, or URL to a file containing the resource to describe"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "containing the resource to describe"
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
cmd.Flags().BoolVar(&describerSettings.ShowEvents, "show-events", true, "If true, display events related to the described object.")
@ -103,7 +95,7 @@ func NewCmdDescribe(f *cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command {
return cmd
}
func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string, options *DescribeOptions, describerSettings *kubectl.DescriberSettings) error {
func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions, describerSettings *kubectl.DescriberSettings) error {
selector := cmdutil.GetFlagString(cmd, "selector")
allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces")
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
@ -113,7 +105,7 @@ func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command,
if allNamespaces {
enforceNamespace = false
}
if len(args) == 0 && len(options.Filenames) == 0 {
if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) {
fmt.Fprint(cmdErr, "You must specify the type of resource to describe. ", valid_resources)
return cmdutil.UsageError(cmd, "Required resource not specified.")
}
@ -122,7 +114,7 @@ func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command,
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
SelectorParam(selector).
ResourceTypeOrNameArgs(true, args...).
Flatten().

View File

@ -78,17 +78,10 @@ var (
kubectl edit svc/docker-registry --output-version=v1 -o json`)
)
// EditOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type EditOptions struct {
Filenames []string
Recursive bool
}
var errExit = fmt.Errorf("exit directly")
func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
options := &EditOptions{}
options := &resource.FilenameOptions{}
// retrieve a list of handled resources from printer as valid args
validArgs, argAliases := []string{}, []string{}
@ -116,9 +109,8 @@ func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
ValidArgs: validArgs,
ArgAliases: argAliases,
}
usage := "Filename, directory, or URL to file to use to edit the resource"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "to use to edit the resource"
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmdutil.AddValidateFlags(cmd)
cmd.Flags().StringP("output", "o", "yaml", "Output format. One of: yaml|json.")
cmd.Flags().String("output-version", "", "Output the formatted object with the given group version (for ex: 'extensions/v1beta1').")
@ -129,7 +121,7 @@ func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
return cmd
}
func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *EditOptions) error {
func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
var printer kubectl.ResourcePrinter
var ext string
var addHeader bool
@ -167,7 +159,7 @@ func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(true, args...).
ContinueOnError().
Flatten().

View File

@ -32,13 +32,6 @@ import (
"k8s.io/kubernetes/pkg/util/validation"
)
// ExposeOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type ExposeOptions struct {
Filenames []string
Recursive bool
}
var (
expose_resources = dedent.Dedent(`
pod (po), service (svc), replicationcontroller (rc),
@ -81,7 +74,7 @@ var (
)
func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &ExposeOptions{}
options := &resource.FilenameOptions{}
validArgs, argAliases := []string{}, []string{}
resources := regexp.MustCompile(`\s*,`).Split(expose_resources, -1)
@ -122,16 +115,15 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().String("session-affinity", "", "If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'")
cmd.Flags().String("cluster-ip", "", "ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.")
usage := "Filename, directory, or URL to a file identifying the resource to expose a service"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
usage := "identifying the resource to expose a service"
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmdutil.AddDryRunFlag(cmd)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
return cmd
}
func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *ExposeOptions) error {
func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
namespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
return err
@ -141,7 +133,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(false, args...).
Flatten().
Do()

View File

@ -35,8 +35,7 @@ import (
// GetOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type GetOptions struct {
Filenames []string
Recursive bool
resource.FilenameOptions
Raw string
}
@ -115,9 +114,8 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma
cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
cmd.Flags().StringSliceP("label-columns", "L", []string{}, "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag options like -L label1 -L label2...")
cmd.Flags().Bool("export", false, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.")
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmdutil.AddInclude3rdPartyFlags(cmd)
cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to request from the server. Uses the transport specified by the kubeconfig file.")
return cmd
@ -168,7 +166,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm
enforceNamespace = false
}
if len(args) == 0 && len(options.Filenames) == 0 {
if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) {
fmt.Fprint(errOut, "You must specify the type of resource to get. ", valid_resources)
return cmdutil.UsageError(cmd, "Required resource not specified.")
}
@ -196,7 +194,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm
if isWatch || isWatchOnly {
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, &options.FilenameOptions).
SelectorParam(selector).
ExportParam(export).
ResourceTypeOrNameArgs(true, args...).
@ -272,7 +270,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, &options.FilenameOptions).
SelectorParam(selector).
ExportParam(export).
ResourceTypeOrNameArgs(true, args...).

View File

@ -37,13 +37,6 @@ import (
"k8s.io/kubernetes/pkg/util/validation"
)
// LabelOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type LabelOptions struct {
Filenames []string
Recursive bool
}
var (
label_long = dedent.Dedent(`
Update the labels on a resource.
@ -73,7 +66,7 @@ var (
)
func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &LabelOptions{}
options := &resource.FilenameOptions{}
// retrieve a list of handled resources from printer as valid args
validArgs, argAliases := []string{}, []string{}
@ -103,9 +96,8 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().Bool("all", false, "select all resources in the namespace of the specified resource types")
cmd.Flags().String("resource-version", "", "If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")
usage := "Filename, directory, or URL to a file identifying the resource to update the labels"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "identifying the resource to update the labels"
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmdutil.AddDryRunFlag(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
@ -180,12 +172,12 @@ func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, label
return nil
}
func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *LabelOptions) error {
func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
resources, labelArgs, err := cmdutil.GetResourcesAndPairs(args, "label")
if err != nil {
return err
}
if len(resources) < 1 && len(options.Filenames) == 0 {
if len(resources) < 1 && cmdutil.IsFilenameEmpty(options.Filenames) {
return cmdutil.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
}
if len(labelArgs) < 1 {
@ -210,7 +202,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
SelectorParam(selector).
ResourceTypeOrNameArgs(all, resources...).
Flatten().

View File

@ -27,6 +27,7 @@ import (
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/unversioned/fake"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime"
)
@ -322,7 +323,7 @@ func TestLabelErrors(t *testing.T) {
for k, v := range testCase.flags {
cmd.Flags().Set(k, v)
}
err := RunLabel(f, buf, cmd, testCase.args, &LabelOptions{})
err := RunLabel(f, buf, cmd, testCase.args, &resource.FilenameOptions{})
if !testCase.errFn(err) {
t.Errorf("%s: unexpected error: %v", k, err)
continue
@ -370,9 +371,8 @@ func TestLabelForResourceFromFile(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdLabel(f, buf)
options := &LabelOptions{
Filenames: []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"},
}
options := &resource.FilenameOptions{}
options.Filenames = []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"}
err := RunLabel(f, buf, cmd, []string{"a=b"}, options)
if err != nil {
@ -421,7 +421,7 @@ func TestLabelMultipleObjects(t *testing.T) {
cmd := NewCmdLabel(f, buf)
cmd.Flags().Set("all", "true")
if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}, &LabelOptions{}); err != nil {
if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}, &resource.FilenameOptions{}); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if strings.Count(buf.String(), "labeled") != len(pods.Items) {

View File

@ -40,9 +40,9 @@ var patchTypes = map[string]api.PatchType{"json": api.JSONPatchType, "merge": ap
// PatchOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type PatchOptions struct {
Filenames []string
Recursive bool
Local bool
resource.FilenameOptions
Local bool
OutputFormat string
}
@ -103,9 +103,8 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to update"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "identifying the resource to update"
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmd.Flags().BoolVar(&options.Local, "local", false, "If true, patch will operate on the content of the file, not the server-side resource.")
@ -146,7 +145,7 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, &options.FilenameOptions).
ResourceTypeOrNameArgs(false, args...).
Flatten().
Do()

View File

@ -35,13 +35,6 @@ import (
"k8s.io/kubernetes/pkg/util/wait"
)
// ReplaceOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type ReplaceOptions struct {
Filenames []string
Recursive bool
}
var (
replace_long = dedent.Dedent(`
Replace a resource by filename or stdin.
@ -66,7 +59,7 @@ var (
)
func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &ReplaceOptions{}
options := &resource.FilenameOptions{}
cmd := &cobra.Command{
Use: "replace -f FILENAME",
@ -81,15 +74,14 @@ func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(err)
},
}
usage := "Filename, directory, or URL to file to use to replace the resource."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
usage := "to use to replace the resource."
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmd.MarkFlagRequired("filename")
cmd.Flags().Bool("force", false, "Delete and re-create the specified resource")
cmd.Flags().Bool("cascade", false, "Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController).")
cmd.Flags().Int("grace-period", -1, "Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.")
cmd.Flags().Duration("timeout", 0, "Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
@ -98,7 +90,7 @@ func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command {
return cmd
}
func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *ReplaceOptions) error {
func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
if len(os.Args) > 1 && os.Args[1] == "update" {
printDeprecationWarning("replace", "update")
}
@ -113,7 +105,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
}
force := cmdutil.GetFlagBool(cmd, "force")
if len(options.Filenames) == 0 {
if cmdutil.IsFilenameEmpty(options.Filenames) {
return cmdutil.UsageError(cmd, "Must specify --filename to replace")
}
@ -135,7 +127,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
Schema(schema).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
Flatten().
Do()
err = r.Err()
@ -171,7 +163,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
})
}
func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *ReplaceOptions) error {
func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *resource.FilenameOptions) error {
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir"))
if err != nil {
return err
@ -205,7 +197,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), runtime.UnstructuredJSONScheme).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(false, args...).RequireObject(false).
Flatten().
Do()
@ -247,7 +239,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
Schema(schema).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
Flatten().
Do()
err = r.Err()

View File

@ -39,12 +39,6 @@ import (
"k8s.io/kubernetes/pkg/util/intstr"
)
// RollingUpdateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type RollingUpdateOptions struct {
Filenames []string
}
var (
rollingUpdate_long = dedent.Dedent(`
Perform a rolling update of the given ReplicationController.
@ -81,7 +75,7 @@ var (
)
func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &RollingUpdateOptions{}
options := &resource.FilenameOptions{}
cmd := &cobra.Command{
Use: "rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)",
@ -147,7 +141,7 @@ func validateArguments(cmd *cobra.Command, filenames, args []string) error {
return utilerrors.NewAggregate(errors)
}
func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *RollingUpdateOptions) error {
func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
if len(os.Args) > 1 && os.Args[1] == "rollingupdate" {
printDeprecationWarning("rolling-update", "rollingupdate")
}
@ -213,7 +207,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
request := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
Schema(schema).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, false, filename).
FilenameParam(enforceNamespace, &resource.FilenameOptions{Recursive: false, Filenames: []string{filename}}).
Do()
obj, err := request.Object()
if err != nil {

View File

@ -28,13 +28,6 @@ import (
"github.com/spf13/cobra"
)
// HistoryOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type HistoryOptions struct {
Filenames []string
Recursive bool
}
var (
history_long = dedent.Dedent(`
View previous rollout revisions and configurations.`)
@ -47,7 +40,7 @@ var (
)
func NewCmdRolloutHistory(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &HistoryOptions{}
options := &resource.FilenameOptions{}
validArgs := []string{"deployment"}
argAliases := kubectl.ResourceAliases(validArgs)
@ -65,14 +58,13 @@ func NewCmdRolloutHistory(f *cmdutil.Factory, out io.Writer) *cobra.Command {
}
cmd.Flags().Int64("revision", 0, "See the details, including podTemplate of the revision specified")
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
return cmd
}
func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *HistoryOptions) error {
if len(args) == 0 && len(options.Filenames) == 0 {
func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error {
if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) {
return cmdutil.UsageError(cmd, "Required resource not specified.")
}
revision := cmdutil.GetFlagInt64(cmd, "revision")
@ -86,7 +78,7 @@ func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []st
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(true, args...).
ContinueOnError().
Latest().

View File

@ -33,14 +33,14 @@ import (
// PauseConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type PauseConfig struct {
resource.FilenameOptions
PauseObject func(object runtime.Object) (bool, error)
Mapper meta.RESTMapper
Typer runtime.ObjectTyper
Infos []*resource.Info
Out io.Writer
Filenames []string
Recursive bool
Out io.Writer
}
var (
@ -59,7 +59,7 @@ var (
)
func NewCmdRolloutPause(f *cmdutil.Factory, out io.Writer) *cobra.Command {
opts := &PauseConfig{}
options := &PauseConfig{}
validArgs := []string{"deployment"}
argAliases := kubectl.ResourceAliases(validArgs)
@ -71,11 +71,11 @@ func NewCmdRolloutPause(f *cmdutil.Factory, out io.Writer) *cobra.Command {
Example: pause_example,
Run: func(cmd *cobra.Command, args []string) {
allErrs := []error{}
err := opts.CompletePause(f, cmd, out, args)
err := options.CompletePause(f, cmd, out, args)
if err != nil {
allErrs = append(allErrs, err)
}
err = opts.RunPause()
err = options.RunPause()
if err != nil {
allErrs = append(allErrs, err)
}
@ -85,14 +85,13 @@ func NewCmdRolloutPause(f *cmdutil.Factory, out io.Writer) *cobra.Command {
ArgAliases: argAliases,
}
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &opts.Recursive)
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
return cmd
}
func (o *PauseConfig) CompletePause(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error {
if len(args) == 0 && len(o.Filenames) == 0 {
if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) {
return cmdutil.UsageError(cmd, cmd.Use)
}
@ -107,7 +106,7 @@ func (o *PauseConfig) CompletePause(f *cmdutil.Factory, cmd *cobra.Command, out
r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, o.Recursive, o.Filenames...).
FilenameParam(enforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(true, args...).
ContinueOnError().
Latest().

View File

@ -33,14 +33,14 @@ import (
// ResumeConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type ResumeConfig struct {
resource.FilenameOptions
ResumeObject func(object runtime.Object) (bool, error)
Mapper meta.RESTMapper
Typer runtime.ObjectTyper
Infos []*resource.Info
Out io.Writer
Filenames []string
Recursive bool
Out io.Writer
}
var (
@ -57,7 +57,7 @@ var (
)
func NewCmdRolloutResume(f *cmdutil.Factory, out io.Writer) *cobra.Command {
opts := &ResumeConfig{}
options := &ResumeConfig{}
validArgs := []string{"deployment"}
argAliases := kubectl.ResourceAliases(validArgs)
@ -69,11 +69,11 @@ func NewCmdRolloutResume(f *cmdutil.Factory, out io.Writer) *cobra.Command {
Example: resume_example,
Run: func(cmd *cobra.Command, args []string) {
allErrs := []error{}
err := opts.CompleteResume(f, cmd, out, args)
err := options.CompleteResume(f, cmd, out, args)
if err != nil {
allErrs = append(allErrs, err)
}
err = opts.RunResume()
err = options.RunResume()
if err != nil {
allErrs = append(allErrs, err)
}
@ -83,14 +83,13 @@ func NewCmdRolloutResume(f *cmdutil.Factory, out io.Writer) *cobra.Command {
ArgAliases: argAliases,
}
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &opts.Recursive)
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
return cmd
}
func (o *ResumeConfig) CompleteResume(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error {
if len(args) == 0 && len(o.Filenames) == 0 {
if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) {
return cmdutil.UsageError(cmd, cmd.Use)
}
@ -105,7 +104,7 @@ func (o *ResumeConfig) CompleteResume(f *cmdutil.Factory, cmd *cobra.Command, ou
r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, o.Recursive, o.Filenames...).
FilenameParam(enforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(true, args...).
ContinueOnError().
Latest().

View File

@ -29,13 +29,6 @@ import (
"github.com/spf13/cobra"
)
// StatusOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type StatusOptions struct {
Filenames []string
Recursive bool
}
var (
status_long = dedent.Dedent(`
Watch the status of current rollout, until it's done.`)
@ -45,7 +38,7 @@ var (
)
func NewCmdRolloutStatus(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &StatusOptions{}
options := &resource.FilenameOptions{}
validArgs := []string{"deployment"}
argAliases := kubectl.ResourceAliases(validArgs)
@ -62,14 +55,13 @@ func NewCmdRolloutStatus(f *cmdutil.Factory, out io.Writer) *cobra.Command {
ArgAliases: argAliases,
}
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
return cmd
}
func RunStatus(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *StatusOptions) error {
if len(args) == 0 && len(options.Filenames) == 0 {
func RunStatus(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error {
if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) {
return cmdutil.UsageError(cmd, "Required resource not specified.")
}
@ -82,7 +74,7 @@ func RunStatus(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(true, args...).
SingleResourceType().
Latest().

View File

@ -33,6 +33,8 @@ import (
// UndoOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type UndoOptions struct {
resource.FilenameOptions
Rollbackers []kubectl.Rollbacker
Mapper meta.RESTMapper
Typer runtime.ObjectTyper
@ -40,9 +42,7 @@ type UndoOptions struct {
ToRevision int64
DryRun bool
Out io.Writer
Filenames []string
Recursive bool
Out io.Writer
}
var (
@ -60,7 +60,7 @@ var (
)
func NewCmdRolloutUndo(f *cmdutil.Factory, out io.Writer) *cobra.Command {
opts := &UndoOptions{}
options := &UndoOptions{}
validArgs := []string{"deployment"}
argAliases := kubectl.ResourceAliases(validArgs)
@ -72,11 +72,11 @@ func NewCmdRolloutUndo(f *cmdutil.Factory, out io.Writer) *cobra.Command {
Example: undo_example,
Run: func(cmd *cobra.Command, args []string) {
allErrs := []error{}
err := opts.CompleteUndo(f, cmd, out, args)
err := options.CompleteUndo(f, cmd, out, args)
if err != nil {
allErrs = append(allErrs, err)
}
err = opts.RunUndo()
err = options.RunUndo()
if err != nil {
allErrs = append(allErrs, err)
}
@ -87,15 +87,14 @@ func NewCmdRolloutUndo(f *cmdutil.Factory, out io.Writer) *cobra.Command {
}
cmd.Flags().Int64("to-revision", 0, "The revision to rollback to. Default to 0 (last revision).")
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage)
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmdutil.AddDryRunFlag(cmd)
cmdutil.AddRecursiveFlag(cmd, &opts.Recursive)
return cmd
}
func (o *UndoOptions) CompleteUndo(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error {
if len(args) == 0 && len(o.Filenames) == 0 {
if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) {
return cmdutil.UsageError(cmd, "Required resource not specified.")
}
@ -111,7 +110,7 @@ func (o *UndoOptions) CompleteUndo(f *cmdutil.Factory, cmd *cobra.Command, out i
r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, o.Recursive, o.Filenames...).
FilenameParam(enforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(true, args...).
ContinueOnError().
Latest().

View File

@ -30,13 +30,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/resource"
)
// ScaleOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type ScaleOptions struct {
Filenames []string
Recursive bool
}
var (
scale_long = dedent.Dedent(`
Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job.
@ -64,7 +57,7 @@ var (
// NewCmdScale returns a cobra command with the appropriate configuration and flags to run scale
func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &ScaleOptions{}
options := &resource.FilenameOptions{}
validArgs := []string{"deployment", "replicaset", "replicationcontroller", "job"}
argAliases := kubectl.ResourceAliases(validArgs)
@ -94,14 +87,13 @@ func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to set a new size"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "identifying the resource to set a new size"
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
return cmd
}
// RunScale executes the scaling
func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *ScaleOptions) error {
func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *resource.FilenameOptions) error {
if len(os.Args) > 1 && os.Args[1] == "resize" {
printDeprecationWarning("scale", "resize")
}
@ -115,7 +107,7 @@ func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(false, args...).
Flatten().
Do()

View File

@ -24,7 +24,6 @@ import (
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime"
@ -34,6 +33,8 @@ import (
// ImageOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type ImageOptions struct {
resource.FilenameOptions
Mapper meta.RESTMapper
Typer runtime.ObjectTyper
Infos []*resource.Info
@ -41,8 +42,6 @@ type ImageOptions struct {
Selector string
Out io.Writer
Err io.Writer
Filenames []string
Recursive bool
ShortOutput bool
All bool
Record bool
@ -97,13 +96,12 @@ func NewCmdImage(f *cmdutil.Factory, out io.Writer) *cobra.Command {
}
cmdutil.AddPrinterFlags(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmd.Flags().BoolVar(&options.All, "all", false, "select all resources in the namespace of the specified resource types")
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.")
cmdutil.AddRecordFlag(cmd)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
return cmd
}
@ -130,7 +128,7 @@ func (o *ImageOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, args []s
builder := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, o.Recursive, o.Filenames...).
FilenameParam(enforceNamespace, &o.FilenameOptions).
Flatten()
if !o.Local {
builder = builder.
@ -148,7 +146,7 @@ func (o *ImageOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, args []s
func (o *ImageOptions) Validate() error {
errors := []error{}
if len(o.Resources) < 1 && len(o.Filenames) == 0 {
if len(o.Resources) < 1 && cmdutil.IsFilenameEmpty(o.Filenames) {
errors = append(errors, fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>"))
}
if len(o.ContainerImages) < 1 {

View File

@ -22,18 +22,10 @@ import (
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
)
// StopOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags()
type StopOptions struct {
Filenames []string
Recursive bool
}
var (
stop_long = dedent.Dedent(`
Deprecated: Gracefully shut down a resource by name or filename.
@ -58,7 +50,7 @@ var (
)
func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &StopOptions{}
options := &resource.FilenameOptions{}
cmd := &cobra.Command{
Use: "stop (-f FILENAME | TYPE (NAME | -l label | --all))",
@ -71,9 +63,8 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(RunStop(f, cmd, args, out, options))
},
}
usage := "Filename, directory, or URL to file of resource(s) to be stopped."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
usage := "of resource(s) to be stopped."
cmdutil.AddFilenameOptionFlags(cmd, options, usage)
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.")
cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful stop.")
@ -84,7 +75,7 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command {
return cmd
}
func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer, options *StopOptions) error {
func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer, options *resource.FilenameOptions) error {
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
return err
@ -95,7 +86,7 @@ func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Write
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
ResourceTypeOrNameArgs(false, args...).
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
FilenameParam(enforceNamespace, options).
SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
SelectAllParam(cmdutil.GetFlagBool(cmd, "all")).
Flatten().

View File

@ -268,6 +268,13 @@ func UsageError(cmd *cobra.Command, format string, args ...interface{}) error {
return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath())
}
func IsFilenameEmpty(filenames []string) bool {
if len(filenames) == 0 {
return true
}
return false
}
// Whether this cmd need watching objects.
func isWatch(cmd *cobra.Command) bool {
if w, err := cmd.Flags().GetBool("watch"); w && err == nil {
@ -355,8 +362,9 @@ func AddValidateFlags(cmd *cobra.Command) {
cmd.MarkFlagFilename("schema-cache-dir")
}
func AddRecursiveFlag(cmd *cobra.Command, value *bool) {
cmd.Flags().BoolVarP(value, "recursive", "R", *value, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.")
func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) {
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, "Filename, directory, or URL to files "+usage)
cmd.Flags().BoolVarP(&options.Recursive, "recursive", "R", options.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.")
}
// AddDryRunFlag adds dry-run flag to a command. Usually used by mutations.

View File

@ -93,6 +93,11 @@ func IsUsageError(err error) bool {
return err == missingResourceError
}
type FilenameOptions struct {
Filenames []string
Recursive bool
}
type resourceTuple struct {
Resource string
Name string
@ -117,7 +122,9 @@ func (b *Builder) Schema(schema validation.Schema) *Builder {
// will cause an error.
// If ContinueOnError() is set prior to this method, objects on the path that are not
// recognized will be ignored (but logged at V(2)).
func (b *Builder) FilenameParam(enforceNamespace, recursive bool, paths ...string) *Builder {
func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *FilenameOptions) *Builder {
recursive := filenameOptions.Recursive
paths := filenameOptions.Filenames
for _, s := range paths {
switch {
case s == "-":

View File

@ -253,7 +253,7 @@ var aRC string = `
func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) {
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, false, "../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml")
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml"}})
test := &testVisitor{}
singular := false
@ -356,7 +356,7 @@ func TestPathBuilderWithMultiple(t *testing.T) {
for _, test := range tests {
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, test.recursive, test.directory).
FilenameParam(false, &FilenameOptions{Recursive: test.recursive, Filenames: []string{test.directory}}).
NamespaceParam("test").DefaultNamespace()
testVisitor := &testVisitor{}
@ -415,7 +415,7 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) {
for _, test := range tests {
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, test.recursive, test.directory).
FilenameParam(false, &FilenameOptions{Recursive: test.recursive, Filenames: []string{test.directory}}).
NamespaceParam("test").DefaultNamespace()
testVisitor := &testVisitor{}
@ -430,7 +430,7 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) {
func TestDirectoryBuilder(t *testing.T) {
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, false, "../../../examples/guestbook/legacy").
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy"}}).
NamespaceParam("test").DefaultNamespace()
test := &testVisitor{}
@ -461,7 +461,7 @@ func TestNamespaceOverride(t *testing.T) {
defer s.Close()
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, false, s.URL).
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
NamespaceParam("test")
test := &testVisitor{}
@ -472,7 +472,7 @@ func TestNamespaceOverride(t *testing.T) {
}
b = NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(true, false, s.URL).
FilenameParam(true, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
NamespaceParam("test")
test = &testVisitor{}
@ -492,7 +492,7 @@ func TestURLBuilder(t *testing.T) {
defer s.Close()
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, false, s.URL).
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
NamespaceParam("foo")
test := &testVisitor{}
@ -521,7 +521,7 @@ func TestURLBuilderRequireNamespace(t *testing.T) {
defer s.Close()
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
FilenameParam(false, false, s.URL).
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
NamespaceParam("test").RequireNamespace()
test := &testVisitor{}
@ -941,7 +941,7 @@ func TestContinueOnErrorVisitor(t *testing.T) {
func TestSingularObject(t *testing.T) {
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
NamespaceParam("test").DefaultNamespace().
FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml").
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).
Flatten().
Do().Object()
@ -961,7 +961,7 @@ func TestSingularObject(t *testing.T) {
func TestSingularObjectNoExtension(t *testing.T) {
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
NamespaceParam("test").DefaultNamespace().
FilenameParam(false, false, "../../../examples/pod").
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/pod"}}).
Flatten().
Do().Object()
@ -1072,7 +1072,7 @@ func TestWatch(t *testing.T) {
}),
}), testapi.Default.Codec()).
NamespaceParam("test").DefaultNamespace().
FilenameParam(false, false, "../../../examples/guestbook/redis-master-service.yaml").Flatten().
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/redis-master-service.yaml"}}).Flatten().
Do().Watch("12")
if err != nil {
@ -1099,8 +1099,8 @@ func TestWatch(t *testing.T) {
func TestWatchMultipleError(t *testing.T) {
_, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
NamespaceParam("test").DefaultNamespace().
FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml").Flatten().
FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml").Flatten().
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten().
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten().
Do().Watch("")
if err == nil {