diff options
author | Dan Duvall <dduvall@wikimedia.org> | 2018-03-06 20:31:58 -0800 |
---|---|---|
committer | Dan Duvall <dduvall@wikimedia.org> | 2018-03-19 15:55:16 -0700 |
commit | eb9b69dd3d710cb7afa1dfb6e23a5987842b21cc (patch) | |
tree | 049b11cc885e4e9f54aac8981c91a1bf3620e7af /vendor/github.com/pborman/getopt/v2/var.go | |
parent | 6896e655eb5cc88b90e66979bc2d862eb92cbb9f (diff) | |
download | blubber-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/var.go')
-rw-r--r-- | vendor/github.com/pborman/getopt/v2/var.go | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/vendor/github.com/pborman/getopt/v2/var.go b/vendor/github.com/pborman/getopt/v2/var.go new file mode 100644 index 0000000..0aaa79c --- /dev/null +++ b/vendor/github.com/pborman/getopt/v2/var.go @@ -0,0 +1,100 @@ +// 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" + "runtime" + "strings" +) + +// Value is the interface to the dynamic value stored in a flag. Flags of type +// Value are declared using the Flag and FlagLong functions. +type Value interface { + // Set converts value into the appropriate type and assigns it to the + // receiver value. Option details are provided via opt (such as the + // flags name). + // + // Set is used to reset the value of an option to its default value + // (which is stored in string form internally). + Set(value string, opt Option) error + + // String returns the value of the flag as a string. + String() string +} + +var thisPackage string + +// init initializes thisPackage to our full package with the trailing . +// included. +func init() { + pc, _, _, ok := runtime.Caller(0) + if !ok { + return + } + f := runtime.FuncForPC(pc) + if f == nil { + return + } + thisPackage = f.Name() + x := strings.LastIndex(thisPackage, "/") + if x < 0 { + return + } + y := strings.Index(thisPackage[x:], ".") + if y < 0 { + return + } + // thisPackage includes the trailing . after the package name. + thisPackage = thisPackage[:x+y+1] +} + +// calledFrom returns a string containing the file and linenumber of the first +// stack frame above us that is not part of this package and is not a test. +// This is used to determine where a flag was initialized. +func calledFrom() string { + for i := 2; ; i++ { + pc, file, line, ok := runtime.Caller(i) + if !ok { + return "" + } + if !strings.HasSuffix(file, "_test.go") { + f := runtime.FuncForPC(pc) + if f != nil && strings.HasPrefix(f.Name(), thisPackage) { + continue + } + } + return fmt.Sprintf("%s:%d", file, line) + } +} + +func (s *Set) addFlag(p Value, name string, short rune, helpvalue ...string) Option { + opt := &option{ + short: short, + long: name, + value: p, + defval: p.String(), + } + + switch len(helpvalue) { + case 2: + opt.name = helpvalue[1] + fallthrough + case 1: + opt.help = helpvalue[0] + case 0: + default: + panic("Too many strings for String helpvalue") + } + if where := calledFrom(); where != "" { + opt.where = where + } + if opt.short == 0 && opt.long == "" { + fmt.Fprintf(stderr, opt.where+": no short or long option given") + exit(1) + } + s.AddOption(opt) + return opt +} |