summaryrefslogtreecommitdiff
path: root/vendor/github.com/pborman/getopt/v2/generic.go
diff options
context:
space:
mode:
authorDan Duvall <dduvall@wikimedia.org>2018-03-06 20:31:58 -0800
committerDan Duvall <dduvall@wikimedia.org>2018-03-19 15:55:16 -0700
commiteb9b69dd3d710cb7afa1dfb6e23a5987842b21cc (patch)
tree049b11cc885e4e9f54aac8981c91a1bf3620e7af /vendor/github.com/pborman/getopt/v2/generic.go
parent6896e655eb5cc88b90e66979bc2d862eb92cbb9f (diff)
downloadblubber-eb9b69dd3d710cb7afa1dfb6e23a5987842b21cc.tar.gz
Allow for configuration policies
Summary: Implements a rough interface for validating configuration against arbitrary policy rules. Policies are provided as YAML and passed via the command line as file paths or remote URIs. The format of policies is: enforcements: - path: <path> rule: <rule> Where `<path>` is a YAML-ish path to a config field and `<rule>` is any expression our config validator understands (expressions built in by the validator library and custom tags defined in `config.validation.go`). Example policy: enforcements: - path: variants.production.base rule: oneof=debian:jessie debian:stretch - path: variants.production.runs.as rule: ne=foo - path: variants.production.node.dependencies rule: isfalse Command flag parsing was implemented in `main.go` to support the new `--policy=uri` flag and improve existing handling of `--version` and the usage statement. Test Plan: Run `go test ./...`. Reviewers: thcipriani, demon, hashar, mmodell, #release-engineering-team Reviewed By: thcipriani, #release-engineering-team Tags: #release-engineering-team Differential Revision: https://phabricator.wikimedia.org/D999
Diffstat (limited to 'vendor/github.com/pborman/getopt/v2/generic.go')
-rw-r--r--vendor/github.com/pborman/getopt/v2/generic.go237
1 files changed, 237 insertions, 0 deletions
diff --git a/vendor/github.com/pborman/getopt/v2/generic.go b/vendor/github.com/pborman/getopt/v2/generic.go
new file mode 100644
index 0000000..913f63b
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/generic.go
@@ -0,0 +1,237 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type generic struct {
+ p interface{}
+}
+
+// Flag is shorthand for CommandLine.Flag.
+func Flag(v interface{}, short rune, helpvalue ...string) Option {
+ return CommandLine.long(v, "", short, helpvalue...)
+}
+
+// FlagLong is shorthand for CommandLine.LongFlag.
+func FlagLong(v interface{}, long string, short rune, helpvalue ...string) Option {
+ return CommandLine.long(v, long, short, helpvalue...)
+}
+
+// Flag calls FlagLong with only a short flag name.
+func (s *Set) Flag(v interface{}, short rune, helpvalue ...string) Option {
+ return s.long(v, "", short, helpvalue...)
+}
+
+// FlagLong returns an Option in Set s for setting v. If long is not "" then
+// the option has a long name, and if short is not 0, the option has a short
+// name. v must either be of type getopt.Value or a pointer to one of the
+// supported builtin types:
+//
+// bool, string, []string
+// int, int8, int16, int32, int64
+// uint, uint8, uint16, uint32, uint64
+// float32, float64
+// time.Duration
+//
+// FlagLong will panic if v is not a getopt.Value or one of the supported
+// builtin types.
+//
+// The default value of the flag is the value of v at the time FlagLong is
+// called.
+func (s *Set) FlagLong(v interface{}, long string, short rune, helpvalue ...string) Option {
+ return s.long(v, long, short, helpvalue...)
+}
+
+func (s *Set) long(v interface{}, long string, short rune, helpvalue ...string) (opt Option) {
+ // Fix up our location when we return.
+ if where := calledFrom(); where != "" {
+ defer func() {
+ if opt, ok := opt.(*option); ok {
+ opt.where = where
+ }
+ }()
+ }
+ switch p := v.(type) {
+ case Value:
+ return s.addFlag(p, long, short, helpvalue...)
+ case *bool:
+ return s.addFlag(&generic{v}, long, short, helpvalue...).SetFlag()
+ case *string, *[]string:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *int, *int8, *int16, *int32, *int64:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *uint, *uint8, *uint16, *uint32, *uint64:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *float32, *float64:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *time.Duration:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ default:
+ panic(fmt.Sprintf("unsupported flag type: %T", v))
+ }
+}
+
+func (g *generic) Set(value string, opt Option) error {
+ strconvErr := func(err error) error {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ switch p := g.p.(type) {
+ case *bool:
+ switch strings.ToLower(value) {
+ case "", "1", "true", "on", "t":
+ *p = true
+ case "0", "false", "off", "f":
+ *p = false
+ default:
+ return fmt.Errorf("invalid value for bool %s: %q", opt.Name(), value)
+ }
+ return nil
+ case *string:
+ *p = value
+ return nil
+ case *[]string:
+ a := strings.Split(value, ",")
+ // If this is the first time we are seen then nil out the
+ // default value.
+ if opt.Count() <= 1 {
+ *p = nil
+ }
+ *p = append(*p, a...)
+ return nil
+ case *int:
+ i64, err := strconv.ParseInt(value, 0, strconv.IntSize)
+ if err == nil {
+ *p = int(i64)
+ }
+ return strconvErr(err)
+ case *int8:
+ i64, err := strconv.ParseInt(value, 0, 8)
+ if err == nil {
+ *p = int8(i64)
+ }
+ return strconvErr(err)
+ case *int16:
+ i64, err := strconv.ParseInt(value, 0, 16)
+ if err == nil {
+ *p = int16(i64)
+ }
+ return strconvErr(err)
+ case *int32:
+ i64, err := strconv.ParseInt(value, 0, 32)
+ if err == nil {
+ *p = int32(i64)
+ }
+ return strconvErr(err)
+ case *int64:
+ i64, err := strconv.ParseInt(value, 0, 64)
+ if err == nil {
+ *p = i64
+ }
+ return strconvErr(err)
+ case *uint:
+ u64, err := strconv.ParseUint(value, 0, strconv.IntSize)
+ if err == nil {
+ *p = uint(u64)
+ }
+ return strconvErr(err)
+ case *uint8:
+ u64, err := strconv.ParseUint(value, 0, 8)
+ if err == nil {
+ *p = uint8(u64)
+ }
+ return strconvErr(err)
+ case *uint16:
+ u64, err := strconv.ParseUint(value, 0, 16)
+ if err == nil {
+ *p = uint16(u64)
+ }
+ return strconvErr(err)
+ case *uint32:
+ u64, err := strconv.ParseUint(value, 0, 32)
+ if err == nil {
+ *p = uint32(u64)
+ }
+ return strconvErr(err)
+ case *uint64:
+ u64, err := strconv.ParseUint(value, 0, 64)
+ if err == nil {
+ *p = u64
+ }
+ return strconvErr(err)
+ case *float32:
+ f64, err := strconv.ParseFloat(value, 32)
+ if err == nil {
+ *p = float32(f64)
+ }
+ return strconvErr(err)
+ case *float64:
+ f64, err := strconv.ParseFloat(value, 64)
+ if err == nil {
+ *p = f64
+ }
+ return strconvErr(err)
+ case *time.Duration:
+ v, err := time.ParseDuration(value)
+ if err == nil {
+ *p = v
+ }
+ return err
+ }
+ panic("internal error")
+}
+
+func (g *generic) String() string {
+ switch p := g.p.(type) {
+ case *bool:
+ if *p {
+ return "true"
+ }
+ return "false"
+ case *string:
+ return *p
+ case *[]string:
+ return strings.Join([]string(*p), ",")
+ case *int:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int8:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int16:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int32:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int64:
+ return strconv.FormatInt(*p, 10)
+ case *uint:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint8:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint16:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint32:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint64:
+ return strconv.FormatUint(*p, 10)
+ case *float32:
+ return strconv.FormatFloat(float64(*p), 'g', -1, 32)
+ case *float64:
+ return strconv.FormatFloat(*p, 'g', -1, 64)
+ case *time.Duration:
+ return p.String()
+ }
+ panic("internal error")
+}