cord-776 create build / runtime containers for autmation uservices
Change-Id: I246973192adef56a250ffe93a5f65fff488840c1
diff --git a/config-generator/vendor/github.com/kelseyhightower/envconfig/.travis.yml b/config-generator/vendor/github.com/kelseyhightower/envconfig/.travis.yml
deleted file mode 100644
index e15301a..0000000
--- a/config-generator/vendor/github.com/kelseyhightower/envconfig/.travis.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-language: go
-
-go:
- - 1.4
- - 1.5
- - 1.6
- - tip
diff --git a/config-generator/vendor/github.com/kelseyhightower/envconfig/README.md b/config-generator/vendor/github.com/kelseyhightower/envconfig/README.md
index dd516a2..09de74b 100644
--- a/config-generator/vendor/github.com/kelseyhightower/envconfig/README.md
+++ b/config-generator/vendor/github.com/kelseyhightower/envconfig/README.md
@@ -87,20 +87,30 @@
```Go
type Specification struct {
- MultiWordVar string `envconfig:"multi_word_var"`
- DefaultVar string `default:"foobar"`
- RequiredVar string `required:"true"`
- IgnoredVar string `ignored:"true"`
+ ManualOverride1 string `envconfig:"manual_override_1"`
+ DefaultVar string `default:"foobar"`
+ RequiredVar string `required:"true"`
+ IgnoredVar string `ignored:"true"`
+ AutoSplitVar string `split_words:"true"`
}
```
-Envconfig will process value for `MultiWordVar` by populating it with the
-value for `MYAPP_MULTI_WORD_VAR`.
+Envconfig has automatic support for CamelCased struct elements when the
+`split_words:"true"` tag is supplied. Without this tag, `AutoSplitVar` above
+would look for an environment variable called `MYAPP_AUTOSPLITVAR`. With the
+setting applied it will look for `MYAPP_AUTO_SPLIT_VAR`. Note that numbers
+will get globbed into the previous word. If the setting does not do the
+right thing, you may use a manual override.
+
+Envconfig will process value for `ManualOverride1` by populating it with the
+value for `MYAPP_MANUAL_OVERRIDE_1`. Without this struct tag, it would have
+instead looked up `MYAPP_MANUALOVERRIDE1`. With the `split_words:"true"` tag
+it would have looked up `MYAPP_MANUAL_OVERRIDE1`.
```Bash
-export MYAPP_MULTI_WORD_VAR="this will be the value"
+export MYAPP_MANUAL_OVERRIDE_1="this will be the value"
-# export MYAPP_MULTIWORDVAR="and this will not"
+# export MYAPP_MANUALOVERRIDE1="and this will not"
```
If envconfig can't find an environment variable value for `MYAPP_DEFAULTVAR`,
@@ -135,6 +145,7 @@
* int8, int16, int32, int64
* bool
* float32, float64
+ * [encoding.TextUnmarshaler](https://golang.org/pkg/encoding/#TextUnmarshaler)
Embedded structs using these fields are also supported.
@@ -159,3 +170,6 @@
Address IPDecoder `envconfig:"DNS_SERVER"`
}
```
+
+Also, envconfig will use a `Set(string) error` method like from the
+[flag.Value](https://godoc.org/flag#Value) interface if implemented.
diff --git a/config-generator/vendor/github.com/kelseyhightower/envconfig/env_os.go b/config-generator/vendor/github.com/kelseyhightower/envconfig/env_os.go
new file mode 100644
index 0000000..a6a014a
--- /dev/null
+++ b/config-generator/vendor/github.com/kelseyhightower/envconfig/env_os.go
@@ -0,0 +1,7 @@
+// +build appengine
+
+package envconfig
+
+import "os"
+
+var lookupEnv = os.LookupEnv
diff --git a/config-generator/vendor/github.com/kelseyhightower/envconfig/env_syscall.go b/config-generator/vendor/github.com/kelseyhightower/envconfig/env_syscall.go
new file mode 100644
index 0000000..9d98085
--- /dev/null
+++ b/config-generator/vendor/github.com/kelseyhightower/envconfig/env_syscall.go
@@ -0,0 +1,7 @@
+// +build !appengine
+
+package envconfig
+
+import "syscall"
+
+var lookupEnv = syscall.Getenv
diff --git a/config-generator/vendor/github.com/kelseyhightower/envconfig/envconfig.go b/config-generator/vendor/github.com/kelseyhightower/envconfig/envconfig.go
index 1daf389..3ad5e7d 100644
--- a/config-generator/vendor/github.com/kelseyhightower/envconfig/envconfig.go
+++ b/config-generator/vendor/github.com/kelseyhightower/envconfig/envconfig.go
@@ -5,12 +5,13 @@
package envconfig
import (
+ "encoding"
"errors"
"fmt"
"reflect"
+ "regexp"
"strconv"
"strings"
- "syscall"
"time"
)
@@ -24,83 +25,164 @@
FieldName string
TypeName string
Value string
+ Err error
}
-// A Decoder is a type that knows how to de-serialize environment variables
-// into itself.
+// Decoder has the same semantics as Setter, but takes higher precedence.
+// It is provided for historical compatibility.
type Decoder interface {
Decode(value string) error
}
+// Setter is implemented by types can self-deserialize values.
+// Any type that implements flag.Value also implements Setter.
+type Setter interface {
+ Set(value string) error
+}
+
func (e *ParseError) Error() string {
- return fmt.Sprintf("envconfig.Process: assigning %[1]s to %[2]s: converting '%[3]s' to type %[4]s", e.KeyName, e.FieldName, e.Value, e.TypeName)
+ return fmt.Sprintf("envconfig.Process: assigning %[1]s to %[2]s: converting '%[3]s' to type %[4]s. details: %[5]s", e.KeyName, e.FieldName, e.Value, e.TypeName, e.Err)
+}
+
+// varInfo maintains information about the configuration variable
+type varInfo struct {
+ Name string
+ Alt string
+ Key string
+ Field reflect.Value
+ Tags reflect.StructTag
+}
+
+// GatherInfo gathers information about the specified struct
+func gatherInfo(prefix string, spec interface{}) ([]varInfo, error) {
+ expr := regexp.MustCompile("([^A-Z]+|[A-Z][^A-Z]+|[A-Z]+)")
+ s := reflect.ValueOf(spec)
+
+ if s.Kind() != reflect.Ptr {
+ return nil, ErrInvalidSpecification
+ }
+ s = s.Elem()
+ if s.Kind() != reflect.Struct {
+ return nil, ErrInvalidSpecification
+ }
+ typeOfSpec := s.Type()
+
+ // over allocate an info array, we will extend if needed later
+ infos := make([]varInfo, 0, s.NumField())
+ for i := 0; i < s.NumField(); i++ {
+ f := s.Field(i)
+ ftype := typeOfSpec.Field(i)
+ if !f.CanSet() || ftype.Tag.Get("ignored") == "true" {
+ continue
+ }
+
+ for f.Kind() == reflect.Ptr {
+ if f.IsNil() {
+ if f.Type().Elem().Kind() != reflect.Struct {
+ // nil pointer to a non-struct: leave it alone
+ break
+ }
+ // nil pointer to struct: create a zero instance
+ f.Set(reflect.New(f.Type().Elem()))
+ }
+ f = f.Elem()
+ }
+
+ // Capture information about the config variable
+ info := varInfo{
+ Name: ftype.Name,
+ Field: f,
+ Tags: ftype.Tag,
+ Alt: strings.ToUpper(ftype.Tag.Get("envconfig")),
+ }
+
+ // Default to the field name as the env var name (will be upcased)
+ info.Key = info.Name
+
+ // Best effort to un-pick camel casing as separate words
+ if ftype.Tag.Get("split_words") == "true" {
+ words := expr.FindAllStringSubmatch(ftype.Name, -1)
+ if len(words) > 0 {
+ var name []string
+ for _, words := range words {
+ name = append(name, words[0])
+ }
+
+ info.Key = strings.Join(name, "_")
+ }
+ }
+ if info.Alt != "" {
+ info.Key = info.Alt
+ }
+ if prefix != "" {
+ info.Key = fmt.Sprintf("%s_%s", prefix, info.Key)
+ }
+ info.Key = strings.ToUpper(info.Key)
+ infos = append(infos, info)
+
+ if f.Kind() == reflect.Struct {
+ // honor Decode if present
+ if decoderFrom(f) == nil && setterFrom(f) == nil && textUnmarshaler(f) == nil {
+ innerPrefix := prefix
+ if !ftype.Anonymous {
+ innerPrefix = info.Key
+ }
+
+ embeddedPtr := f.Addr().Interface()
+ embeddedInfos, err := gatherInfo(innerPrefix, embeddedPtr)
+ if err != nil {
+ return nil, err
+ }
+ infos = append(infos[:len(infos)-1], embeddedInfos...)
+
+ continue
+ }
+ }
+ }
+ return infos, nil
}
// Process populates the specified struct based on environment variables
func Process(prefix string, spec interface{}) error {
- s := reflect.ValueOf(spec)
+ infos, err := gatherInfo(prefix, spec)
- if s.Kind() != reflect.Ptr {
- return ErrInvalidSpecification
- }
- s = s.Elem()
- if s.Kind() != reflect.Struct {
- return ErrInvalidSpecification
- }
- typeOfSpec := s.Type()
- for i := 0; i < s.NumField(); i++ {
- f := s.Field(i)
- if !f.CanSet() || typeOfSpec.Field(i).Tag.Get("ignored") == "true" {
- continue
- }
+ for _, info := range infos {
- if typeOfSpec.Field(i).Anonymous && f.Kind() == reflect.Struct {
- embeddedPtr := f.Addr().Interface()
- if err := Process(prefix, embeddedPtr); err != nil {
- return err
- }
- f.Set(reflect.ValueOf(embeddedPtr).Elem())
- }
-
- alt := typeOfSpec.Field(i).Tag.Get("envconfig")
- fieldName := typeOfSpec.Field(i).Name
- if alt != "" {
- fieldName = alt
- }
- key := strings.ToUpper(fmt.Sprintf("%s_%s", prefix, fieldName))
// `os.Getenv` cannot differentiate between an explicitly set empty value
// and an unset value. `os.LookupEnv` is preferred to `syscall.Getenv`,
- // but it is only available in go1.5 or newer.
- value, ok := syscall.Getenv(key)
- if !ok && alt != "" {
- key := strings.ToUpper(fieldName)
- value, ok = syscall.Getenv(key)
+ // but it is only available in go1.5 or newer. We're using Go build tags
+ // here to use os.LookupEnv for >=go1.5
+ value, ok := lookupEnv(info.Key)
+ if !ok && info.Alt != "" {
+ value, ok = lookupEnv(info.Alt)
}
- def := typeOfSpec.Field(i).Tag.Get("default")
+ def := info.Tags.Get("default")
if def != "" && !ok {
value = def
}
- req := typeOfSpec.Field(i).Tag.Get("required")
+ req := info.Tags.Get("required")
if !ok && def == "" {
if req == "true" {
- return fmt.Errorf("required key %s missing value", key)
+ return fmt.Errorf("required key %s missing value", info.Key)
}
continue
}
- err := processField(value, f)
+ err := processField(value, info.Field)
if err != nil {
return &ParseError{
- KeyName: key,
- FieldName: fieldName,
- TypeName: f.Type().String(),
+ KeyName: info.Key,
+ FieldName: info.Name,
+ TypeName: info.Field.Type().String(),
Value: value,
+ Err: err,
}
}
}
- return nil
+
+ return err
}
// MustProcess is the same as Process but panics if an error occurs
@@ -117,6 +199,15 @@
if decoder != nil {
return decoder.Decode(value)
}
+ // look for Set method if Decode not defined
+ setter := setterFrom(field)
+ if setter != nil {
+ return setter.Set(value)
+ }
+
+ if t := textUnmarshaler(field); t != nil {
+ return t.UnmarshalText([]byte(value))
+ }
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
@@ -179,23 +270,29 @@
return nil
}
-func decoderFrom(field reflect.Value) Decoder {
- if field.CanInterface() {
- dec, ok := field.Interface().(Decoder)
- if ok {
- return dec
- }
+func interfaceFrom(field reflect.Value, fn func(interface{}, *bool)) {
+ // it may be impossible for a struct field to fail this check
+ if !field.CanInterface() {
+ return
}
-
- // also check if pointer-to-type implements Decoder,
- // and we can get a pointer to our field
- if field.CanAddr() {
- field = field.Addr()
- dec, ok := field.Interface().(Decoder)
- if ok {
- return dec
- }
+ var ok bool
+ fn(field.Interface(), &ok)
+ if !ok && field.CanAddr() {
+ fn(field.Addr().Interface(), &ok)
}
+}
- return nil
+func decoderFrom(field reflect.Value) (d Decoder) {
+ interfaceFrom(field, func(v interface{}, ok *bool) { d, *ok = v.(Decoder) })
+ return d
+}
+
+func setterFrom(field reflect.Value) (s Setter) {
+ interfaceFrom(field, func(v interface{}, ok *bool) { s, *ok = v.(Setter) })
+ return s
+}
+
+func textUnmarshaler(field reflect.Value) (t encoding.TextUnmarshaler) {
+ interfaceFrom(field, func(v interface{}, ok *bool) { t, *ok = v.(encoding.TextUnmarshaler) })
+ return t
}
diff --git a/config-generator/vendor/github.com/kelseyhightower/envconfig/usage.go b/config-generator/vendor/github.com/kelseyhightower/envconfig/usage.go
new file mode 100644
index 0000000..4870237
--- /dev/null
+++ b/config-generator/vendor/github.com/kelseyhightower/envconfig/usage.go
@@ -0,0 +1,152 @@
+// Copyright (c) 2016 Kelsey Hightower and others. All rights reserved.
+// Use of this source code is governed by the MIT License that can be found in
+// the LICENSE file.
+
+package envconfig
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+ "text/tabwriter"
+ "text/template"
+)
+
+const (
+ // DefaultListFormat constant to use to display usage in a list format
+ DefaultListFormat = `This application is configured via the environment. The following environment
+variables can be used:
+{{range .}}
+{{usage_key .}}
+ [description] {{usage_description .}}
+ [type] {{usage_type .}}
+ [default] {{usage_default .}}
+ [required] {{usage_required .}}{{end}}
+`
+ // DefaultTableFormat constant to use to display usage in a tabluar format
+ DefaultTableFormat = `This application is configured via the environment. The following environment
+variables can be used:
+
+KEY TYPE DEFAULT REQUIRED DESCRIPTION
+{{range .}}{{usage_key .}} {{usage_type .}} {{usage_default .}} {{usage_required .}} {{usage_description .}}
+{{end}}`
+)
+
+var (
+ decoderType = reflect.TypeOf((*Decoder)(nil)).Elem()
+ setterType = reflect.TypeOf((*Setter)(nil)).Elem()
+ unmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+)
+
+func implementsInterface(t reflect.Type) bool {
+ return t.Implements(decoderType) ||
+ reflect.PtrTo(t).Implements(decoderType) ||
+ t.Implements(setterType) ||
+ reflect.PtrTo(t).Implements(setterType) ||
+ t.Implements(unmarshalerType) ||
+ reflect.PtrTo(t).Implements(unmarshalerType)
+}
+
+// toTypeDescription converts Go types into a human readable description
+func toTypeDescription(t reflect.Type) string {
+ switch t.Kind() {
+ case reflect.Array, reflect.Slice:
+ return fmt.Sprintf("Comma-separated list of %s", toTypeDescription(t.Elem()))
+ case reflect.Ptr:
+ return toTypeDescription(t.Elem())
+ case reflect.Struct:
+ if implementsInterface(t) && t.Name() != "" {
+ return t.Name()
+ }
+ return ""
+ case reflect.String:
+ name := t.Name()
+ if name != "" && name != "string" {
+ return name
+ }
+ return "String"
+ case reflect.Bool:
+ name := t.Name()
+ if name != "" && name != "bool" {
+ return name
+ }
+ return "True or False"
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ name := t.Name()
+ if name != "" && !strings.HasPrefix(name, "int") {
+ return name
+ }
+ return "Integer"
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ name := t.Name()
+ if name != "" && !strings.HasPrefix(name, "uint") {
+ return name
+ }
+ return "Unsigned Integer"
+ case reflect.Float32, reflect.Float64:
+ name := t.Name()
+ if name != "" && !strings.HasPrefix(name, "float") {
+ return name
+ }
+ return "Float"
+ }
+ return fmt.Sprintf("%+v", t)
+}
+
+// Usage writes usage information to stderr using the default header and table format
+func Usage(prefix string, spec interface{}) error {
+ // The default is to output the usage information as a table
+ // Create tabwriter instance to support table output
+ tabs := tabwriter.NewWriter(os.Stdout, 1, 0, 4, ' ', 0)
+
+ err := Usagef(prefix, spec, tabs, DefaultTableFormat)
+ tabs.Flush()
+ return err
+}
+
+// Usagef writes usage information to the specified io.Writer using the specifed template specification
+func Usagef(prefix string, spec interface{}, out io.Writer, format string) error {
+
+ // Specify the default usage template functions
+ functions := template.FuncMap{
+ "usage_key": func(v varInfo) string { return v.Key },
+ "usage_description": func(v varInfo) string { return v.Tags.Get("desc") },
+ "usage_type": func(v varInfo) string { return toTypeDescription(v.Field.Type()) },
+ "usage_default": func(v varInfo) string { return v.Tags.Get("default") },
+ "usage_required": func(v varInfo) (string, error) {
+ req := v.Tags.Get("required")
+ if req != "" {
+ reqB, err := strconv.ParseBool(req)
+ if err != nil {
+ return "", err
+ }
+ if reqB {
+ req = "true"
+ }
+ }
+ return req, nil
+ },
+ }
+
+ tmpl, err := template.New("envconfig").Funcs(functions).Parse(format)
+ if err != nil {
+ return err
+ }
+
+ return Usaget(prefix, spec, out, tmpl)
+}
+
+// Usaget writes usage information to the specified io.Writer using the specified template
+func Usaget(prefix string, spec interface{}, out io.Writer, tmpl *template.Template) error {
+ // gather first
+ infos, err := gatherInfo(prefix, spec)
+ if err != nil {
+ return err
+ }
+
+ return tmpl.Execute(out, infos)
+}