mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Merge pull request #35408 from xilabao/add-secret-to-pflag
Automatic merge from submit-queue (batch tested with PRs 35408, 41915, 41992, 41964, 41925) add secret option to flag To resolve the issue of security(pr #35030 ), > @smarterclayton commented 5 days ago > This is unfortunately not all flags that could be secrets. The best option would be to add support in spf13/pflag to tag a flag as a secret, and then use that bit to determine the list. > > Also, Command() could be used in contexts that need exact parameters (for subshell execution), so we would need to add a new method or extend the signature here to allow exact flags to be retrieved. we could add a secret option to the flags.
This commit is contained in:
commit
082cfac707
2
Godeps/Godeps.json
generated
2
Godeps/Godeps.json
generated
@ -2237,7 +2237,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "5ccb023bc27df288a957c5e994cd44fd19619465"
|
||||
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/viper",
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -106,7 +106,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "5ccb023bc27df288a957c5e994cd44fd19619465"
|
||||
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/ugorji/go/codec",
|
||||
|
2
staging/src/k8s.io/apiserver/Godeps/Godeps.json
generated
2
staging/src/k8s.io/apiserver/Godeps/Godeps.json
generated
@ -551,7 +551,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "5ccb023bc27df288a957c5e994cd44fd19619465"
|
||||
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/assert",
|
||||
|
2
staging/src/k8s.io/client-go/Godeps/Godeps.json
generated
2
staging/src/k8s.io/client-go/Godeps/Godeps.json
generated
@ -170,7 +170,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "5ccb023bc27df288a957c5e994cd44fd19619465"
|
||||
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/assert",
|
||||
|
@ -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
|
||||
|
@ -278,7 +278,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "5ccb023bc27df288a957c5e994cd44fd19619465"
|
||||
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/ugorji/go/codec",
|
||||
|
@ -266,7 +266,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "5ccb023bc27df288a957c5e994cd44fd19619465"
|
||||
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/ugorji/go/codec",
|
||||
|
3
vendor/BUILD
vendored
3
vendor/BUILD
vendored
@ -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"],
|
||||
)
|
||||
|
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
Normal file
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.idea/*
|
||||
|
6
vendor/github.com/spf13/pflag/README.md
generated
vendored
6
vendor/github.com/spf13/pflag/README.md
generated
vendored
@ -1,4 +1,6 @@
|
||||
[](https://travis-ci.org/spf13/pflag)
|
||||
[](https://goreportcard.com/report/github.com/spf13/pflag)
|
||||
[](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.
|
||||
|
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
Normal file
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
146
vendor/github.com/spf13/pflag/flag.go
generated
vendored
146
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -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)
|
||||
|
3
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
3
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
@ -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
|
||||
|
2
vendor/github.com/spf13/pflag/ip.go
generated
vendored
2
vendor/github.com/spf13/pflag/ip.go
generated
vendored
@ -6,8 +6,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = strings.TrimSpace
|
||||
|
||||
// -- net.IP value
|
||||
type ipValue net.IP
|
||||
|
||||
|
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
Normal file
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
2
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
2
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
@ -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)
|
||||
|
6
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
6
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
@ -1,11 +1,5 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var _ = fmt.Fprint
|
||||
|
||||
// -- stringArray Value
|
||||
type stringArrayValue struct {
|
||||
value *[]string
|
||||
|
5
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
5
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
@ -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 {
|
||||
|
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
Normal file
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user