diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index a88658348b5..80e0c413c72 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2237,7 +2237,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "5ccb023bc27df288a957c5e994cd44fd19619465" + "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" }, { "ImportPath": "github.com/spf13/viper", diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index f61ff45ac2a..bf71e61e7c7 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -184,7 +184,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro return err } - changeCause := f.Command() + changeCause := f.Command(cmd, false) mapper, typer, err := f.UnstructuredObject() if err != nil { diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index 98085275df6..51f73320fc7 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -258,7 +258,7 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti } if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } } @@ -313,7 +313,7 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti } if cmdutil.ShouldRecord(cmd, info) { - if patch, patchType, err := cmdutil.ChangeResourcePatch(info, f.Command()); err == nil { + if patch, patchType, err := cmdutil.ChangeResourcePatch(info, f.Command(cmd, true)); err == nil { if _, err = helper.Patch(info.Namespace, info.Name, patchType, patch); err != nil { glog.V(4).Infof("error recording reason: %v", err) } diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 0fb1e726528..0c1a796bb34 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -156,7 +156,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s return err } if cmdutil.ShouldRecord(cmd, hpa) { - if err := cmdutil.RecordChangeCause(hpa.Object, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(hpa.Object, f.Command(cmd, false)); err != nil { return err } object = hpa.Object diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 90adab0346f..17d9089c536 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -154,7 +154,7 @@ func RunCreate(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opt } if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } } diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index 04555d2cdd3..efdccfe9558 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -537,7 +537,7 @@ func visitAnnotation(cmd *cobra.Command, f cmdutil.Factory, annotationVisitor re return err } if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { return err } } diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 3fac9d093c7..f5690fdea66 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -248,7 +248,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri return err } if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(object, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(object, f.Command(cmd, false)); err != nil { return err } } diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 14b20b7718d..edae2d88e73 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -179,7 +179,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { return err } - changeCause := f.Command() + changeCause := f.Command(cmd, false) mapper, typer, err := f.UnstructuredObject() if err != nil { diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index 33236fbdea2..c3fe85ea9fb 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -190,7 +190,7 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin infoCopy := *info infoCopy.Object = patchedObj infoCopy.VersionedObject = patchedObj - if patch, patchType, err := cmdutil.ChangeResourcePatch(&infoCopy, f.Command()); err == nil { + if patch, patchType, err := cmdutil.ChangeResourcePatch(&infoCopy, f.Command(cmd, true)); err == nil { if _, err = helper.Patch(info.Namespace, info.Name, patchType, patch); err != nil { glog.V(4).Infof("error recording reason: %v", err) } diff --git a/pkg/kubectl/cmd/replace.go b/pkg/kubectl/cmd/replace.go index e6383607b9d..c3d737279e3 100644 --- a/pkg/kubectl/cmd/replace.go +++ b/pkg/kubectl/cmd/replace.go @@ -151,7 +151,7 @@ func RunReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str } if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { return cmdutil.AddSourceToErr("replacing", info.Source, err) } } @@ -272,7 +272,7 @@ func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s } if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { return cmdutil.AddSourceToErr("replacing", info.Source, err) } } diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 2cbcadbcc93..01e4a01ceb5 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -585,7 +585,7 @@ func createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command, generator kube return nil, "", nil, nil, err } if cmdutil.GetRecordFlag(cmd) || len(annotations[kubectl.ChangeCauseAnnotation]) > 0 { - if err := cmdutil.RecordChangeCause(obj, f.Command()); err != nil { + if err := cmdutil.RecordChangeCause(obj, f.Command(cmd, false)); err != nil { return nil, "", nil, nil, err } } diff --git a/pkg/kubectl/cmd/scale.go b/pkg/kubectl/cmd/scale.go index 2526dbf70bf..930233d6002 100644 --- a/pkg/kubectl/cmd/scale.go +++ b/pkg/kubectl/cmd/scale.go @@ -164,7 +164,7 @@ func RunScale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin return err } if cmdutil.ShouldRecord(cmd, info) { - patchBytes, patchType, err := cmdutil.ChangeResourcePatch(info, f.Command()) + patchBytes, patchType, err := cmdutil.ChangeResourcePatch(info, f.Command(cmd, true)) if err != nil { return err } diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index f4cdd75c413..327652ec293 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -119,7 +119,7 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st o.Encoder = f.JSONEncoder() o.ShortOutput = cmdutil.GetFlagString(cmd, "output") == "name" o.Record = cmdutil.GetRecordFlag(cmd) - o.ChangeCause = f.Command() + o.ChangeCause = f.Command(cmd, false) o.PrintObject = f.PrintObject o.DryRun = cmdutil.GetDryRunFlag(cmd) o.Output = cmdutil.GetFlagString(cmd, "output") diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index 4edb588c06c..2525a10fc20 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -131,7 +131,7 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args o.Encoder = f.JSONEncoder() o.ShortOutput = cmdutil.GetFlagString(cmd, "output") == "name" o.Record = cmdutil.GetRecordFlag(cmd) - o.ChangeCause = f.Command() + o.ChangeCause = f.Command(cmd, false) o.PrintObject = f.PrintObject o.Cmd = cmd diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index ea486b87128..00a67c9ca39 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -112,7 +112,7 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ return err } - o.changeCause = f.Command() + o.changeCause = f.Command(cmd, false) mapper, _ := f.Object() o.mapper = mapper o.encoder = f.JSONEncoder() diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index 065d09e978e..fc2e174af25 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -435,7 +435,7 @@ func (f *FakeFactory) EditorEnvs() []string { func (f *FakeFactory) PrintObjectSpecificMessage(obj runtime.Object, out io.Writer) { } -func (f *FakeFactory) Command() string { +func (f *FakeFactory) Command(*cobra.Command, bool) string { return f.tf.Command } @@ -640,7 +640,7 @@ func (f *fakeAPIFactory) DefaultNamespace() (string, bool, error) { return f.tf.Namespace, false, f.tf.Err } -func (f *fakeAPIFactory) Command() string { +func (f *fakeAPIFactory) Command(*cobra.Command, bool) string { return f.tf.Command } diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index e19ce2e600c..bfee99ac68d 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -131,7 +131,7 @@ type ClientAccessFactory interface { FlagSet() *pflag.FlagSet // Command will stringify and return all environment arguments ie. a command run by a client // using the factory. - Command() string + Command(cmd *cobra.Command, showSecrets bool) string // BindFlags adds any flags that are common to all kubectl sub commands. BindFlags(flags *pflag.FlagSet) // BindExternalFlags adds any flags defined by external projects (not part of pflags) diff --git a/pkg/kubectl/cmd/util/factory_client_access.go b/pkg/kubectl/cmd/util/factory_client_access.go index 605a5bdf9c0..e1fd883a74b 100644 --- a/pkg/kubectl/cmd/util/factory_client_access.go +++ b/pkg/kubectl/cmd/util/factory_client_access.go @@ -332,14 +332,35 @@ func (f *ring0Factory) FlagSet() *pflag.FlagSet { return f.flags } -// TODO: We need to filter out stuff like secrets. -func (f *ring0Factory) Command() string { +// Set showSecrets false to filter out stuff like secrets. +func (f *ring0Factory) Command(cmd *cobra.Command, showSecrets bool) string { if len(os.Args) == 0 { return "" } + + flags := "" + parseFunc := func(flag *pflag.Flag, value string) error { + flags = flags + " --" + flag.Name + if set, ok := flag.Annotations["classified"]; showSecrets || !ok || len(set) == 0 { + flags = flags + "=" + value + } else { + flags = flags + "=CLASSIFIED" + } + return nil + } + var err error + err = cmd.Flags().ParseAll(os.Args[1:], parseFunc) + if err != nil || !cmd.Flags().Parsed() { + return "" + } + + args := "" + if arguments := cmd.Flags().Args(); len(arguments) > 0 { + args = " " + strings.Join(arguments, " ") + } + base := filepath.Base(os.Args[0]) - args := append([]string{base}, os.Args[1:]...) - return strings.Join(args, " ") + return base + args + flags } func (f *ring0Factory) BindFlags(flags *pflag.FlagSet) { diff --git a/staging/src/k8s.io/apimachinery/Godeps/Godeps.json b/staging/src/k8s.io/apimachinery/Godeps/Godeps.json index 9819b650fa8..42d09684597 100644 --- a/staging/src/k8s.io/apimachinery/Godeps/Godeps.json +++ b/staging/src/k8s.io/apimachinery/Godeps/Godeps.json @@ -106,7 +106,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "5ccb023bc27df288a957c5e994cd44fd19619465" + "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" }, { "ImportPath": "github.com/ugorji/go/codec", diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index 6aada184bbd..2e48b55555d 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -551,7 +551,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "5ccb023bc27df288a957c5e994cd44fd19619465" + "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" }, { "ImportPath": "github.com/stretchr/testify/assert", diff --git a/staging/src/k8s.io/client-go/Godeps/Godeps.json b/staging/src/k8s.io/client-go/Godeps/Godeps.json index 58658ce96a7..667e2f77760 100644 --- a/staging/src/k8s.io/client-go/Godeps/Godeps.json +++ b/staging/src/k8s.io/client-go/Godeps/Godeps.json @@ -170,7 +170,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "5ccb023bc27df288a957c5e994cd44fd19619465" + "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" }, { "ImportPath": "github.com/stretchr/testify/assert", diff --git a/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go b/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go index 8622981a9e7..f18aa6a4ae2 100644 --- a/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go +++ b/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go @@ -85,16 +85,23 @@ type FlagInfo struct { Description string } +// AddSecretAnnotation add secret flag to Annotation. +func (f FlagInfo) AddSecretAnnotation(flags *pflag.FlagSet) FlagInfo { + flags.SetAnnotation(f.LongName, "classified", []string{"true"}) + return f +} + // BindStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered -func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) { +func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo { // you can't register a flag without a long name if len(f.LongName) > 0 { flags.StringVarP(target, f.LongName, f.ShortName, f.Default, f.Description) } + return f } // BindBoolFlag binds the flag based on the provided info. If LongName == "", nothing is registered -func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) { +func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo { // you can't register a flag without a long name if len(f.LongName) > 0 { // try to parse Default as a bool. If it fails, assume false @@ -105,6 +112,7 @@ func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) { flags.BoolVarP(target, f.LongName, f.ShortName, boolVal, f.Description) } + return f } const ( @@ -180,12 +188,12 @@ func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNam // BindAuthInfoFlags is a convenience method to bind the specified flags to their associated variables func BindAuthInfoFlags(authInfo *clientcmdapi.AuthInfo, flags *pflag.FlagSet, flagNames AuthOverrideFlags) { - flagNames.ClientCertificate.BindStringFlag(flags, &authInfo.ClientCertificate) - flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey) - flagNames.Token.BindStringFlag(flags, &authInfo.Token) - flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate) - flagNames.Username.BindStringFlag(flags, &authInfo.Username) - flagNames.Password.BindStringFlag(flags, &authInfo.Password) + flagNames.ClientCertificate.BindStringFlag(flags, &authInfo.ClientCertificate).AddSecretAnnotation(flags) + flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey).AddSecretAnnotation(flags) + flagNames.Token.BindStringFlag(flags, &authInfo.Token).AddSecretAnnotation(flags) + flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate).AddSecretAnnotation(flags) + flagNames.Username.BindStringFlag(flags, &authInfo.Username).AddSecretAnnotation(flags) + flagNames.Password.BindStringFlag(flags, &authInfo.Password).AddSecretAnnotation(flags) } // BindClusterFlags is a convenience method to bind the specified flags to their associated variables diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index 900decf774e..74cdbb13f0b 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -278,7 +278,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "5ccb023bc27df288a957c5e994cd44fd19619465" + "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" }, { "ImportPath": "github.com/ugorji/go/codec", diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index 486dd24cb5e..cc7885a41ea 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -266,7 +266,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "5ccb023bc27df288a957c5e994cd44fd19619465" + "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" }, { "ImportPath": "github.com/ugorji/go/codec", diff --git a/vendor/BUILD b/vendor/BUILD index 950de33fbd4..29132ac3f10 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -6487,6 +6487,7 @@ go_library( name = "github.com/spf13/pflag", srcs = [ "github.com/spf13/pflag/bool.go", + "github.com/spf13/pflag/bool_slice.go", "github.com/spf13/pflag/count.go", "github.com/spf13/pflag/duration.go", "github.com/spf13/pflag/flag.go", @@ -6499,6 +6500,7 @@ go_library( "github.com/spf13/pflag/int8.go", "github.com/spf13/pflag/int_slice.go", "github.com/spf13/pflag/ip.go", + "github.com/spf13/pflag/ip_slice.go", "github.com/spf13/pflag/ipmask.go", "github.com/spf13/pflag/ipnet.go", "github.com/spf13/pflag/string.go", @@ -6509,6 +6511,7 @@ go_library( "github.com/spf13/pflag/uint32.go", "github.com/spf13/pflag/uint64.go", "github.com/spf13/pflag/uint8.go", + "github.com/spf13/pflag/uint_slice.go", ], tags = ["automanaged"], ) diff --git a/vendor/github.com/spf13/pflag/.gitignore b/vendor/github.com/spf13/pflag/.gitignore new file mode 100644 index 00000000000..c3da2901346 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.gitignore @@ -0,0 +1,2 @@ +.idea/* + diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md index 08ad9456588..eefb46dec83 100644 --- a/vendor/github.com/spf13/pflag/README.md +++ b/vendor/github.com/spf13/pflag/README.md @@ -1,4 +1,6 @@ [![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag) +[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag) ## Description @@ -106,9 +108,9 @@ that give one-letter shorthands for flags. You can use these by appending var ip = flag.IntP("flagname", "f", 1234, "help message") var flagvar bool func init() { - flag.BoolVarP("boolname", "b", true, "help message") + flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") } -flag.VarP(&flagVar, "varname", "v", 1234, "help message") +flag.VarP(&flagVal, "varname", "v", "help message") ``` Shorthand letters can be used with single dashes on the command line. diff --git a/vendor/github.com/spf13/pflag/bool_slice.go b/vendor/github.com/spf13/pflag/bool_slice.go new file mode 100644 index 00000000000..5af02f1a75a --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool_slice.go @@ -0,0 +1,147 @@ +package pflag + +import ( + "io" + "strconv" + "strings" +) + +// -- boolSlice Value +type boolSliceValue struct { + value *[]bool + changed bool +} + +func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue { + bsv := new(boolSliceValue) + bsv.value = p + *bsv.value = val + return bsv +} + +// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag. +// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended. +func (s *boolSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + boolStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse boolean values into slice + out := make([]bool, 0, len(boolStrSlice)) + for _, boolStr := range boolStrSlice { + b, err := strconv.ParseBool(strings.TrimSpace(boolStr)) + if err != nil { + return err + } + out = append(out, b) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *boolSliceValue) Type() string { + return "boolSlice" +} + +// String defines a "native" format for this boolean slice flag value. +func (s *boolSliceValue) String() string { + + boolStrSlice := make([]string, len(*s.value)) + for i, b := range *s.value { + boolStrSlice[i] = strconv.FormatBool(b) + } + + out, _ := writeAsCSV(boolStrSlice) + + return "[" + out + "]" +} + +func boolSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []bool{}, nil + } + ss := strings.Split(val, ",") + out := make([]bool, len(ss)) + for i, t := range ss { + var err error + out[i], err = strconv.ParseBool(t) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetBoolSlice returns the []bool value of a flag with the given name. +func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) { + val, err := f.getFlagType(name, "boolSlice", boolSliceConv) + if err != nil { + return []bool{}, err + } + return val.([]bool), nil +} + +// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSliceVar defines a []bool flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, "", value, usage) + return &p +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func BoolSlice(name string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, "", value, usage) +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index fa815642ed0..746af6327e4 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -487,9 +487,76 @@ func UnquoteUsage(flag *Flag) (name string, usage string) { return } -// FlagUsages Returns a string containing the usage information for all flags in -// the FlagSet -func (f *FlagSet) FlagUsages() string { +// Splits the string `s` on whitespace into an initial substring up to +// `i` runes in length and the remainder. Will go `slop` over `i` if +// that encompasses the entire string (which allows the caller to +// avoid short orphan words on the final line). +func wrapN(i, slop int, s string) (string, string) { + if i+slop > len(s) { + return s, "" + } + + w := strings.LastIndexAny(s[:i], " \t") + if w <= 0 { + return s, "" + } + + return s[:w], s[w+1:] +} + +// Wraps the string `s` to a maximum width `w` with leading indent +// `i`. The first line is not indented (this is assumed to be done by +// caller). Pass `w` == 0 to do no wrapping +func wrap(i, w int, s string) string { + if w == 0 { + return s + } + + // space between indent i and end of line width w into which + // we should wrap the text. + wrap := w - i + + var r, l string + + // Not enough space for sensible wrapping. Wrap as a block on + // the next line instead. + if wrap < 24 { + i = 16 + wrap = w - i + r += "\n" + strings.Repeat(" ", i) + } + // If still not enough space then don't even try to wrap. + if wrap < 24 { + return s + } + + // Try to avoid short orphan words on the final line, by + // allowing wrapN to go a bit over if that would fit in the + // remainder of the line. + slop := 5 + wrap = wrap - slop + + // Handle first line, which is indented by the caller (or the + // special case above) + l, s = wrapN(wrap, slop, s) + r = r + l + + // Now wrap the rest + for s != "" { + var t string + + t, s = wrapN(wrap, slop, s) + r = r + "\n" + strings.Repeat(" ", i) + t + } + + return r + +} + +// FlagUsagesWrapped returns a string containing the usage information +// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no +// wrapping) +func (f *FlagSet) FlagUsagesWrapped(cols int) string { x := new(bytes.Buffer) lines := make([]string, 0, len(f.formal)) @@ -546,12 +613,19 @@ func (f *FlagSet) FlagUsages() string { for _, line := range lines { sidx := strings.Index(line, "\x00") spacing := strings.Repeat(" ", maxlen-sidx) - fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:]) + // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx + fmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) } return x.String() } +// FlagUsages returns a string containing the usage information for all flags in +// the FlagSet +func (f *FlagSet) FlagUsages() string { + return f.FlagUsagesWrapped(0) +} + // PrintDefaults prints to standard error the default values of all defined command-line flags. func PrintDefaults() { CommandLine.PrintDefaults() @@ -635,7 +709,7 @@ func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag { // VarP is like Var, but accepts a shorthand letter that can be used after a single dash. func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { - _ = f.VarPF(value, name, shorthand, usage) + f.VarPF(value, name, shorthand, usage) } // AddFlag will add the flag to the FlagSet @@ -752,7 +826,7 @@ func containsShorthand(arg, shorthand string) bool { return strings.Contains(arg, shorthand) } -func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) { +func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { a = args name := s[2:] if len(name) == 0 || name[0] == '-' || name[0] == '=' { @@ -786,11 +860,11 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) err = f.failf("flag needs an argument: %s", s) return } - err = f.setFlag(flag, value, s) + err = fn(flag, value, s) return } -func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) { +func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) { if strings.HasPrefix(shorthands, "test.") { return } @@ -825,16 +899,16 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShor err = f.failf("flag needs an argument: %q in -%s", c, shorthands) return } - err = f.setFlag(flag, value, shorthands) + err = fn(flag, value, shorthands) return } -func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) { +func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) { a = args shorthands := s[1:] for len(shorthands) > 0 { - shorthands, a, err = f.parseSingleShortArg(shorthands, args) + shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn) if err != nil { return } @@ -843,7 +917,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) return } -func (f *FlagSet) parseArgs(args []string) (err error) { +func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) { for len(args) > 0 { s := args[0] args = args[1:] @@ -863,9 +937,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) { f.args = append(f.args, args...) break } - args, err = f.parseLongArg(s, args) + args, err = f.parseLongArg(s, args, fn) } else { - args, err = f.parseShortArg(s, args) + args, err = f.parseShortArg(s, args, fn) } if err != nil { return @@ -881,7 +955,41 @@ func (f *FlagSet) parseArgs(args []string) (err error) { func (f *FlagSet) Parse(arguments []string) error { f.parsed = true f.args = make([]string, 0, len(arguments)) - err := f.parseArgs(arguments) + + assign := func(flag *Flag, value, origArg string) error { + return f.setFlag(flag, value, origArg) + } + + err := f.parseArgs(arguments, assign) + if err != nil { + switch f.errorHandling { + case ContinueOnError: + return err + case ExitOnError: + os.Exit(2) + case PanicOnError: + panic(err) + } + } + return nil +} + +type parseFunc func(flag *Flag, value, origArg string) error + +// ParseAll parses flag definitions from the argument list, which should not +// include the command name. The arguments for fn are flag and value. Must be +// called after all flags in the FlagSet are defined and before flags are +// accessed by the program. The return value will be ErrHelp if -help was set +// but not defined. +func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error { + f.parsed = true + f.args = make([]string, 0, len(arguments)) + + assign := func(flag *Flag, value, origArg string) error { + return fn(flag, value) + } + + err := f.parseArgs(arguments, assign) if err != nil { switch f.errorHandling { case ContinueOnError: @@ -907,6 +1015,14 @@ func Parse() { CommandLine.Parse(os.Args[1:]) } +// ParseAll parses the command-line flags from os.Args[1:] and called fn for each. +// The arguments for fn are flag and value. Must be called after all flags are +// defined and before flags are accessed by the program. +func ParseAll(fn func(flag *Flag, value string) error) { + // Ignore errors; CommandLine is set for ExitOnError. + CommandLine.ParseAll(os.Args[1:], fn) +} + // SetInterspersed sets whether to support interspersed option/non-option arguments. func SetInterspersed(interspersed bool) { CommandLine.SetInterspersed(interspersed) diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go index b056147fd87..c4f47ebe590 100644 --- a/vendor/github.com/spf13/pflag/golangflag.go +++ b/vendor/github.com/spf13/pflag/golangflag.go @@ -6,13 +6,10 @@ package pflag import ( goflag "flag" - "fmt" "reflect" "strings" ) -var _ = fmt.Print - // flagValueWrapper implements pflag.Value around a flag.Value. The main // difference here is the addition of the Type method that returns a string // name of the type. As this is generally unknown, we approximate that with diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go index 88a17430a09..3d414ba69fe 100644 --- a/vendor/github.com/spf13/pflag/ip.go +++ b/vendor/github.com/spf13/pflag/ip.go @@ -6,8 +6,6 @@ import ( "strings" ) -var _ = strings.TrimSpace - // -- net.IP value type ipValue net.IP diff --git a/vendor/github.com/spf13/pflag/ip_slice.go b/vendor/github.com/spf13/pflag/ip_slice.go new file mode 100644 index 00000000000..7dd196fe3fb --- /dev/null +++ b/vendor/github.com/spf13/pflag/ip_slice.go @@ -0,0 +1,148 @@ +package pflag + +import ( + "fmt" + "io" + "net" + "strings" +) + +// -- ipSlice Value +type ipSliceValue struct { + value *[]net.IP + changed bool +} + +func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue { + ipsv := new(ipSliceValue) + ipsv.value = p + *ipsv.value = val + return ipsv +} + +// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag. +// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended. +func (s *ipSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + ipStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse ip values into slice + out := make([]net.IP, 0, len(ipStrSlice)) + for _, ipStr := range ipStrSlice { + ip := net.ParseIP(strings.TrimSpace(ipStr)) + if ip == nil { + return fmt.Errorf("invalid string being converted to IP address: %s", ipStr) + } + out = append(out, ip) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *ipSliceValue) Type() string { + return "ipSlice" +} + +// String defines a "native" format for this net.IP slice flag value. +func (s *ipSliceValue) String() string { + + ipStrSlice := make([]string, len(*s.value)) + for i, ip := range *s.value { + ipStrSlice[i] = ip.String() + } + + out, _ := writeAsCSV(ipStrSlice) + + return "[" + out + "]" +} + +func ipSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Emtpy string would cause a slice with one (empty) entry + if len(val) == 0 { + return []net.IP{}, nil + } + ss := strings.Split(val, ",") + out := make([]net.IP, len(ss)) + for i, sval := range ss { + ip := net.ParseIP(strings.TrimSpace(sval)) + if ip == nil { + return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) + } + out[i] = ip + } + return out, nil +} + +// GetIPSlice returns the []net.IP value of a flag with the given name +func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) { + val, err := f.getFlagType(name, "ipSlice", ipSliceConv) + if err != nil { + return []net.IP{}, err + } + return val.([]net.IP), nil +} + +// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of that flag. +func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, "", value, usage) + return &p +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of the flag. +func IPSlice(name string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, "", value, usage) +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ipnet.go b/vendor/github.com/spf13/pflag/ipnet.go index 149b764b1e8..e2c1b8bcd53 100644 --- a/vendor/github.com/spf13/pflag/ipnet.go +++ b/vendor/github.com/spf13/pflag/ipnet.go @@ -27,8 +27,6 @@ func (*ipNetValue) Type() string { return "ipNet" } -var _ = strings.TrimSpace - func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue { *p = val return (*ipNetValue)(p) diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go index 93b4e43290a..276b7ed49ed 100644 --- a/vendor/github.com/spf13/pflag/string_array.go +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -1,11 +1,5 @@ package pflag -import ( - "fmt" -) - -var _ = fmt.Fprint - // -- stringArray Value type stringArrayValue struct { value *[]string diff --git a/vendor/github.com/spf13/pflag/string_slice.go b/vendor/github.com/spf13/pflag/string_slice.go index 7829cfafb29..05eee75438d 100644 --- a/vendor/github.com/spf13/pflag/string_slice.go +++ b/vendor/github.com/spf13/pflag/string_slice.go @@ -3,12 +3,9 @@ package pflag import ( "bytes" "encoding/csv" - "fmt" "strings" ) -var _ = fmt.Fprint - // -- stringSlice Value type stringSliceValue struct { value *[]string @@ -39,7 +36,7 @@ func writeAsCSV(vals []string) (string, error) { return "", err } w.Flush() - return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil + return strings.TrimSuffix(b.String(), "\n"), nil } func (s *stringSliceValue) Set(val string) error { diff --git a/vendor/github.com/spf13/pflag/uint_slice.go b/vendor/github.com/spf13/pflag/uint_slice.go new file mode 100644 index 00000000000..edd94c600af --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint_slice.go @@ -0,0 +1,126 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- uintSlice Value +type uintSliceValue struct { + value *[]uint + changed bool +} + +func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue { + uisv := new(uintSliceValue) + uisv.value = p + *uisv.value = val + return uisv +} + +func (s *uintSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return err + } + out[i] = uint(u) + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *uintSliceValue) Type() string { + return "uintSlice" +} + +func (s *uintSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func uintSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []uint{}, nil + } + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return nil, err + } + out[i] = uint(u) + } + return out, nil +} + +// GetUintSlice returns the []uint value of a flag with the given name. +func (f *FlagSet) GetUintSlice(name string) ([]uint, error) { + val, err := f.getFlagType(name, "uintSlice", uintSliceConv) + if err != nil { + return []uint{}, err + } + return val.([]uint), nil +} + +// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string. +// The argument p points to a []uint variable in which to store the value of the flag. +func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSliceVar defines a uint[] flag with specified name, default value, and usage string. +// The argument p points to a uint[] variable in which to store the value of the flag. +func UintSliceVar(p *[]uint, name string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, "", value, usage) + return &p +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func UintSlice(name string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, "", value, usage) +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, shorthand, value, usage) +}