// Merge all of the flags from fsFrom into fsTo. func AddPFlagSetToPFlagSet(fsFrom *pflag.FlagSet, fsTo *pflag.FlagSet) { fsFrom.VisitAll(func(f *pflag.Flag) { if fsTo.Lookup(f.Name) == nil { fsTo.AddFlag(f) } }) }
// findConfigurationConflicts iterates over the provided flags searching for // duplicated configurations and unknown keys. It returns an error with all the conflicts if // it finds any. func findConfigurationConflicts(config map[string]interface{}, flags *pflag.FlagSet) error { // 1. Search keys from the file that we don't recognize as flags. unknownKeys := make(map[string]interface{}) for key, value := range config { if flag := flags.Lookup(key); flag == nil { unknownKeys[key] = value } } // 2. Discard values that implement NamedOption. // Their configuration name differs from their flag name, like `labels` and `label`. if len(unknownKeys) > 0 { unknownNamedConflicts := func(f *pflag.Flag) { if namedOption, ok := f.Value.(opts.NamedOption); ok { if _, valid := unknownKeys[namedOption.Name()]; valid { delete(unknownKeys, namedOption.Name()) } } } flags.VisitAll(unknownNamedConflicts) } if len(unknownKeys) > 0 { var unknown []string for key := range unknownKeys { unknown = append(unknown, key) } return fmt.Errorf("the following directives don't match any configuration option: %s", strings.Join(unknown, ", ")) } var conflicts []string printConflict := func(name string, flagValue, fileValue interface{}) string { return fmt.Sprintf("%s: (from flag: %v, from file: %v)", name, flagValue, fileValue) } // 3. Search keys that are present as a flag and as a file option. duplicatedConflicts := func(f *pflag.Flag) { // search option name in the json configuration payload if the value is a named option if namedOption, ok := f.Value.(opts.NamedOption); ok { if optsValue, ok := config[namedOption.Name()]; ok { conflicts = append(conflicts, printConflict(namedOption.Name(), f.Value.String(), optsValue)) } } else { // search flag name in the json configuration payload for _, name := range []string{f.Name, f.Shorthand} { if value, ok := config[name]; ok { conflicts = append(conflicts, printConflict(name, f.Value.String(), value)) break } } } } flags.Visit(duplicatedConflicts) if len(conflicts) > 0 { return fmt.Errorf("the following directives are specified both as a flag and in the configuration file: %s", strings.Join(conflicts, ", ")) } return nil }
func genFlagResult(flags *pflag.FlagSet) []cmdOption { result := make([]cmdOption, 0) flags.VisitAll(func(flag *pflag.Flag) { // Todo, when we mark a shorthand is deprecated, but specify an empty message. // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { opt := cmdOption{ flag.Name, flag.Shorthand, flag.DefValue, forceMultiLine(flag.Usage), } result = append(result, opt) } else { opt := cmdOption{ Name: flag.Name, DefaultValue: forceMultiLine(flag.DefValue), Usage: forceMultiLine(flag.Usage), } result = append(result, opt) } }) return result }
func deploymentDefaults(fs *pflag.FlagSet, f *fg.Flags, args []string) { // Merge Options fs.VisitAll(func(flag *pflag.Flag) { if !flag.Changed { value, ok := f.Options.Get(flag.Name) if ok { svalue := fmt.Sprintf("%v", value) err := fs.Set(flag.Name, svalue) if err != nil { Exitf("Error in option '%s': %#v\n", flag.Name, err) } } } }) if f.Local { f.StopDelay = 5 * time.Second f.DestroyDelay = 3 * time.Second f.SliceDelay = 5 * time.Second } if f.JobPath == "" && len(args) >= 1 { f.JobPath = args[0] } if f.ClusterPath == "" && len(args) >= 2 { f.ClusterPath = args[1] } }
func manPrintFlags(out *bytes.Buffer, flags *pflag.FlagSet) { flags.VisitAll(func(flag *pflag.Flag) { if len(flag.Deprecated) > 0 { return } format := "" if len(flag.Shorthand) > 0 { format = "**-%s**, **--%s**" } else { format = "%s**--%s**" } if len(flag.NoOptDefVal) > 0 { format = format + "[" } if flag.Value.Type() == "string" { // put quotes on the value format = format + "=%q" } else { format = format + "=%s" } if len(flag.NoOptDefVal) > 0 { format = format + "]" } format = format + "\n\t%s\n\n" fmt.Fprintf(out, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) }) }
func rktFlagUsages(flagSet *pflag.FlagSet) string { x := new(bytes.Buffer) flagSet.VisitAll(func(flag *pflag.Flag) { if len(flag.Deprecated) > 0 || flag.Hidden { return } format := "" if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { format = " -%s, --%s" } else { format = " %s --%s" } if len(flag.NoOptDefVal) > 0 { format = format + "[" } if flag.Value.Type() == "string" { // put quotes on the value format = format + "=%q" } else { format = format + "=%s" } if len(flag.NoOptDefVal) > 0 { format = format + "]" } format = format + "\t%s\n" shorthand := flag.Shorthand fmt.Fprintf(x, format, shorthand, flag.Name, flag.DefValue, flag.Usage) }) return x.String() }
func printFlags(out *bytes.Buffer, flags *pflag.FlagSet) { flags.VisitAll(func(flag *pflag.Flag) { if flag.Hidden { return } format := "**--%s**=%s\n\t%s\n\n" if flag.Value.Type() == "string" { // put quotes on the value format = "**--%s**=%q\n\t%s\n\n" } defValue := flag.DefValue if flag.Value.Type() == "duration" { defValue = "0" } if len(flag.Annotations["manpage-def-value"]) > 0 { defValue = flag.Annotations["manpage-def-value"][0] } // Todo, when we mark a shorthand is deprecated, but specify an empty message. // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { format = "**-%s**, " + format fmt.Fprintf(out, format, flag.Shorthand, flag.Name, defValue, flag.Usage) } else { fmt.Fprintf(out, format, flag.Name, defValue, flag.Usage) } }) }
func getFlags(flagset *pflag.FlagSet) (flags []*pflag.Flag) { flags = make([]*pflag.Flag, 0) flagset.VisitAll(func(f *pflag.Flag) { flags = append(flags, f) }) return }
func (v *Viper) BindPFlags(flags *pflag.FlagSet) (err error) { flags.VisitAll(func(flag *pflag.Flag) { if err = v.BindPFlag(flag.Name, flag); err != nil { return } }) return nil }
// getConflictFreeConfiguration loads the configuration from a JSON file. // It compares that configuration with the one provided by the flags, // and returns an error if there are conflicts. func getConflictFreeConfiguration(configFile string, flags *pflag.FlagSet) (*Config, error) { b, err := ioutil.ReadFile(configFile) if err != nil { return nil, err } var config Config var reader io.Reader if flags != nil { var jsonConfig map[string]interface{} reader = bytes.NewReader(b) if err := json.NewDecoder(reader).Decode(&jsonConfig); err != nil { return nil, err } configSet := configValuesSet(jsonConfig) if err := findConfigurationConflicts(configSet, flags); err != nil { return nil, err } // Override flag values to make sure the values set in the config file with nullable values, like `false`, // are not overridden by default truthy values from the flags that were not explicitly set. // See https://github.com/docker/docker/issues/20289 for an example. // // TODO: Rewrite configuration logic to avoid same issue with other nullable values, like numbers. namedOptions := make(map[string]interface{}) for key, value := range configSet { f := flags.Lookup(key) if f == nil { // ignore named flags that don't match namedOptions[key] = value continue } if _, ok := f.Value.(boolValue); ok { f.Value.Set(fmt.Sprintf("%v", value)) } } if len(namedOptions) > 0 { // set also default for mergeVal flags that are boolValue at the same time. flags.VisitAll(func(f *pflag.Flag) { if opt, named := f.Value.(opts.NamedOption); named { v, set := namedOptions[opt.Name()] _, boolean := f.Value.(boolValue) if set && boolean { f.Value.Set(fmt.Sprintf("%v", v)) } } }) } config.valuesSet = configSet } reader = bytes.NewReader(b) err = json.NewDecoder(reader).Decode(&config) return &config, err }
func sansAdditionalFlags(flags *flag.FlagSet) *flag.FlagSet { fs := &flag.FlagSet{} flags.VisitAll(func(f *flag.Flag) { if c.AdditionalFlags.Lookup(f.Name) == nil { fs.AddFlag(f) } }) return fs }
func (c *CLI) sansDriverFlags(flags *flag.FlagSet) *flag.FlagSet { fs := &flag.FlagSet{} flags.VisitAll(func(f *flag.Flag) { if c.driverFlags().Lookup(f.Name) == nil { fs.AddFlag(f) } }) return fs }
func flagsNotIntersected(l *flag.FlagSet, r *flag.FlagSet) *flag.FlagSet { f := flag.NewFlagSet("notIntersected", flag.ContinueOnError) l.VisitAll(func(flag *flag.Flag) { if r.Lookup(flag.Name) == nil { f.AddFlag(flag) } }) return f }
// Test if the named flag is a boolean flag. func isBooleanShortFlag(name string, f *flag.FlagSet) bool { result := false f.VisitAll(func(f *flag.Flag) { if f.Shorthand == name && f.Value.Type() == "bool" { result = true } }) return result }
func visibleFlags(l *flag.FlagSet) *flag.FlagSet { hidden := "help" f := flag.NewFlagSet("visible", flag.ContinueOnError) l.VisitAll(func(flag *flag.Flag) { if flag.Name != hidden { f.AddFlag(flag) } }) return f }
// ChecksumFlagSet will generate a FNV of the *set* values in a FlagSet. func ChecksumFlagSet(flagSet *pflag.FlagSet, flagFilter func(flag *pflag.Flag) bool) []byte { h := fnv.New32a() flagSet.VisitAll(func(flag *pflag.Flag) { if flagFilter != nil && !flagFilter(flag) { return } h.Write([]byte(flag.Name)) h.Write([]byte(flag.Value.String())) }) return h.Sum(nil) }
// Parse the Options func NewOptions(flags *pflag.FlagSet) Options { result := Options{} flags.VisitAll(func(flag *pflag.Flag) { opt := &Option{ Name: flag.Name, Shorthand: flag.Shorthand, DefaultValue: flag.DefValue, Usage: flag.Usage, } result = append(result, opt) }) return result }
// SetPflagsFromEnv is similar to SetFlagsFromEnv. However, the accepted flagset type is pflag.FlagSet // and it does not do any logging. func SetPflagsFromEnv(prefix string, fs *pflag.FlagSet) error { var err error alreadySet := make(map[string]bool) usedEnvKey := make(map[string]bool) fs.VisitAll(func(f *pflag.Flag) { if f.Changed { alreadySet[flagToEnv(prefix, f.Name)] = true } if serr := setFlagFromEnv(fs, prefix, f.Name, usedEnvKey, alreadySet, false); serr != nil { err = serr } }) return err }
func printFlags(out *bytes.Buffer, flags *pflag.FlagSet) { flags.VisitAll(func(flag *pflag.Flag) { format := "**--%s**=%s\n\t%s\n\n" if flag.Value.Type() == "string" { // put quotes on the value format = "**--%s**=%q\n\t%s\n\n" } if len(flag.Shorthand) > 0 { format = "**-%s**, " + format } else { format = "%s" + format } fmt.Fprintf(out, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) }) }
// getFlagsFromEnv parses all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // environment variables. Environment variables take the name of the flag but // are UPPERCASE, have the given prefix, and any dashes are replaced by // underscores - for example: some-flag => PREFIX_SOME_FLAG func getFlagsFromEnv(prefix string, fs *pflag.FlagSet) { alreadySet := make(map[string]bool) fs.Visit(func(f *pflag.Flag) { alreadySet[f.Name] = true }) fs.VisitAll(func(f *pflag.Flag) { if !alreadySet[f.Name] { key := strings.ToUpper(prefix + "_" + strings.Replace(f.Name, "-", "_", -1)) val := os.Getenv(key) if val != "" { fs.Set(f.Name, val) } } }) }
// SetFlagsFromEnv parses all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // environment variables. Environment variables take the name of the flag but // are UPPERCASE, and any dashes are replaced by underscores. Environment // variables additionally are prefixed by the given string followed by // and underscore. For example, if prefix=PREFIX: some-flag => PREFIX_SOME_FLAG func SetFlagsFromEnv(fs *flag.FlagSet, prefix string) (err error) { alreadySet := make(map[string]bool) fs.Visit(func(f *flag.Flag) { alreadySet[f.Name] = true }) fs.VisitAll(func(f *flag.Flag) { if !alreadySet[f.Name] { key := prefix + "_" + strings.ToUpper(strings.Replace(f.Name, "-", "_", -1)) val := os.Getenv(key) if val != "" { if serr := fs.Set(f.Name, val); serr != nil { err = fmt.Errorf("invalid value %q for %s: %v", val, key, serr) } } } }) return err }
func (v *Viper) BindPFlags(flags *pflag.FlagSet) (err error) { flags.VisitAll(func(flag *pflag.Flag) { if err != nil { // an error has been encountered in one of the previous flags return } err = v.BindPFlag(flag.Name, flag) switch flag.Value.Type() { case "int", "int8", "int16", "int32", "int64": v.SetDefault(flag.Name, cast.ToInt(flag.Value.String())) case "bool": v.SetDefault(flag.Name, cast.ToBool(flag.Value.String())) default: v.SetDefault(flag.Name, flag.Value.String()) } }) return }
func printFlags(out *bytes.Buffer, flags *pflag.FlagSet) { flags.VisitAll(func(flag *pflag.Flag) { format := "**--%s**=%s\n\t%s\n\n" if flag.Value.Type() == "string" { // put quotes on the value format = "**--%s**=%q\n\t%s\n\n" } // Todo, when we mark a shorthand is deprecated, but specify an empty message. // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { format = "**-%s**, " + format fmt.Fprintf(out, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) } else { fmt.Fprintf(out, format, flag.Name, flag.DefValue, flag.Usage) } }) }
// loadArgumentsFromCluster and uses its data to update the given flagset. func loadArgumentsFromCluster(flagSet *pflag.FlagSet, requireProfile bool) { if cluster == "" { return } profile := "" parts := strings.Split(cluster, "@") if len(parts) == 2 { profile = parts[0] cluster = parts[1] } else if requireProfile { Exitf("No cluster profile specified (-c profile@cluster)") } clustersPath := os.Getenv("PULCY_CLUSTERS") if clustersPath == "" { clustersPath = "config/clusters" } path, err := resolvePath(cluster, clustersPath, ".hcl") if err != nil { Exitf("Cannot resolve cluster path: %#v", err) } c, err := clusterpkg.ParseClusterFromFile(path) if err != nil { Exitf("Cannot load cluster from path '%s': %#v", clustersPath, err) } values, err := c.ResolveProfile(profile) if err != nil { Exitf("Cannot resolve profile '%s' in cluster path '%s': %#v", profile, clustersPath, err) } flagSet.VisitAll(func(flag *pflag.Flag) { if !flag.Changed { value, ok := values[flag.Name] if ok { err := flagSet.Set(flag.Name, fmt.Sprintf("%v", value)) if err != nil { Exitf("Error in option '%s': %#v\n", flag.Name, err) } log.Debugf("--%s=%v", flag.Name, value) } } }) }
func flagsUsages(f *flag.FlagSet) string { x := new(bytes.Buffer) f.VisitAll(func(flag *flag.Flag) { format := "--%s=%s: %s\n" if flag.Value.Type() == "string" { format = "--%s='%s': %s\n" } if len(flag.Shorthand) > 0 { format = " -%s, " + format } else { format = " %s " + format } fmt.Fprintf(x, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) }) return x.String() }