Add HashiCorp Nomad provider (#483)
* provider: adding Nomad provider * updating CONTRIBUTING.md with Nomad provider * updated README.md by adding the Nomad provider * fix typo * adding nomad/api and nomad/testutil deps * adding Nomad binary dependency for provider tests * fixed the nomad binary download command step and added tolerations to the nomad provider. * adding nomad provider demo gif * adding my name to authors * adding two missing go-rootcerts files after dep ensure * delete pod comment
This commit is contained in:
committed by
Robbie Zhang
parent
5796be449b
commit
a46e1dd2ce
28
vendor/github.com/hashicorp/nomad/helper/args/args.go
generated
vendored
Normal file
28
vendor/github.com/hashicorp/nomad/helper/args/args.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package args
|
||||
|
||||
import "regexp"
|
||||
|
||||
var (
|
||||
envRe = regexp.MustCompile(`\${[a-zA-Z0-9_\-\.]+}`)
|
||||
)
|
||||
|
||||
// ReplaceEnv takes an arg and replaces all occurrences of environment variables.
|
||||
// If the variable is found in the passed map it is replaced, otherwise the
|
||||
// original string is returned.
|
||||
func ReplaceEnv(arg string, environments ...map[string]string) string {
|
||||
return envRe.ReplaceAllStringFunc(arg, func(arg string) string {
|
||||
stripped := arg[2 : len(arg)-1]
|
||||
for _, env := range environments {
|
||||
if value, ok := env[stripped]; ok {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
return arg
|
||||
})
|
||||
}
|
||||
|
||||
// ReplaceEnvWithPlaceHolder replaces all occurrences of environment variables with the placeholder string.
|
||||
func ReplaceEnvWithPlaceHolder(arg string, placeholder string) string {
|
||||
return envRe.ReplaceAllString(arg, placeholder)
|
||||
}
|
||||
66
vendor/github.com/hashicorp/nomad/helper/discover/discover.go
generated
vendored
Normal file
66
vendor/github.com/hashicorp/nomad/helper/discover/discover.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Checks the current executable, then $GOPATH/bin, and finally the CWD, in that
|
||||
// order. If it can't be found, an error is returned.
|
||||
func NomadExecutable() (string, error) {
|
||||
nomadExe := "nomad"
|
||||
if runtime.GOOS == "windows" {
|
||||
nomadExe = "nomad.exe"
|
||||
}
|
||||
|
||||
// Check the current executable.
|
||||
bin, err := os.Executable()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to determine the nomad executable: %v", err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(bin); err == nil && isNomad(bin, nomadExe) {
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
// Check the $PATH
|
||||
if bin, err := exec.LookPath(nomadExe); err == nil {
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
// Check the $GOPATH.
|
||||
bin = filepath.Join(os.Getenv("GOPATH"), "bin", nomadExe)
|
||||
if _, err := os.Stat(bin); err == nil {
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
// Check the CWD.
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Could not find Nomad executable (%v): %v", nomadExe, err)
|
||||
}
|
||||
|
||||
bin = filepath.Join(pwd, nomadExe)
|
||||
if _, err := os.Stat(bin); err == nil {
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
// Check CWD/bin
|
||||
bin = filepath.Join(pwd, "bin", nomadExe)
|
||||
if _, err := os.Stat(bin); err == nil {
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Could not find Nomad executable (%v)", nomadExe)
|
||||
}
|
||||
|
||||
func isNomad(path, nomadExe string) bool {
|
||||
if strings.HasSuffix(path, ".test") || strings.HasSuffix(path, ".test.exe") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
129
vendor/github.com/hashicorp/nomad/helper/flatmap/flatmap.go
generated
vendored
Normal file
129
vendor/github.com/hashicorp/nomad/helper/flatmap/flatmap.go
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
package flatmap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Flatten takes an object and returns a flat map of the object. The keys of the
|
||||
// map is the path of the field names until a primitive field is reached and the
|
||||
// value is a string representation of the terminal field.
|
||||
func Flatten(obj interface{}, filter []string, primitiveOnly bool) map[string]string {
|
||||
flat := make(map[string]string)
|
||||
v := reflect.ValueOf(obj)
|
||||
if !v.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
flatten("", v, primitiveOnly, false, flat)
|
||||
for _, f := range filter {
|
||||
if _, ok := flat[f]; ok {
|
||||
delete(flat, f)
|
||||
}
|
||||
}
|
||||
return flat
|
||||
}
|
||||
|
||||
// flatten recursively calls itself to create a flatmap representation of the
|
||||
// passed value. The results are stored into the output map and the keys are
|
||||
// the fields prepended with the passed prefix.
|
||||
// XXX: A current restriction is that maps only support string keys.
|
||||
func flatten(prefix string, v reflect.Value, primitiveOnly, enteredStruct bool, output map[string]string) {
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
output[prefix] = fmt.Sprintf("%v", v.Bool())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
output[prefix] = fmt.Sprintf("%v", v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
output[prefix] = fmt.Sprintf("%v", v.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
output[prefix] = fmt.Sprintf("%v", v.Float())
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
output[prefix] = fmt.Sprintf("%v", v.Complex())
|
||||
case reflect.String:
|
||||
output[prefix] = fmt.Sprintf("%v", v.String())
|
||||
case reflect.Invalid:
|
||||
output[prefix] = "nil"
|
||||
case reflect.Ptr:
|
||||
if primitiveOnly && enteredStruct {
|
||||
return
|
||||
}
|
||||
|
||||
e := v.Elem()
|
||||
if !e.IsValid() {
|
||||
output[prefix] = "nil"
|
||||
}
|
||||
flatten(prefix, e, primitiveOnly, enteredStruct, output)
|
||||
case reflect.Map:
|
||||
for _, k := range v.MapKeys() {
|
||||
if k.Kind() == reflect.Interface {
|
||||
k = k.Elem()
|
||||
}
|
||||
|
||||
if k.Kind() != reflect.String {
|
||||
panic(fmt.Sprintf("%q: map key is not string: %s", prefix, k))
|
||||
}
|
||||
|
||||
flatten(getSubKeyPrefix(prefix, k.String()), v.MapIndex(k), primitiveOnly, enteredStruct, output)
|
||||
}
|
||||
case reflect.Struct:
|
||||
if primitiveOnly && enteredStruct {
|
||||
return
|
||||
}
|
||||
enteredStruct = true
|
||||
|
||||
t := v.Type()
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
name := t.Field(i).Name
|
||||
val := v.Field(i)
|
||||
if val.Kind() == reflect.Interface && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
flatten(getSubPrefix(prefix, name), val, primitiveOnly, enteredStruct, output)
|
||||
}
|
||||
case reflect.Interface:
|
||||
if primitiveOnly {
|
||||
return
|
||||
}
|
||||
|
||||
e := v.Elem()
|
||||
if !e.IsValid() {
|
||||
output[prefix] = "nil"
|
||||
return
|
||||
}
|
||||
flatten(prefix, e, primitiveOnly, enteredStruct, output)
|
||||
case reflect.Array, reflect.Slice:
|
||||
if primitiveOnly {
|
||||
return
|
||||
}
|
||||
|
||||
if v.Kind() == reflect.Slice && v.IsNil() {
|
||||
output[prefix] = "nil"
|
||||
return
|
||||
}
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
flatten(fmt.Sprintf("%s[%d]", prefix, i), v.Index(i), primitiveOnly, enteredStruct, output)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("prefix %q; unsupported type %v", prefix, v.Kind()))
|
||||
}
|
||||
}
|
||||
|
||||
// getSubPrefix takes the current prefix and the next subfield and returns an
|
||||
// appropriate prefix.
|
||||
func getSubPrefix(curPrefix, subField string) string {
|
||||
if curPrefix != "" {
|
||||
return fmt.Sprintf("%s.%s", curPrefix, subField)
|
||||
}
|
||||
return fmt.Sprintf("%s", subField)
|
||||
}
|
||||
|
||||
// getSubKeyPrefix takes the current prefix and the next subfield and returns an
|
||||
// appropriate prefix for a map field.
|
||||
func getSubKeyPrefix(curPrefix, subField string) string {
|
||||
if curPrefix != "" {
|
||||
return fmt.Sprintf("%s[%s]", curPrefix, subField)
|
||||
}
|
||||
return fmt.Sprintf("%s", subField)
|
||||
}
|
||||
304
vendor/github.com/hashicorp/nomad/helper/funcs.go
generated
vendored
Normal file
304
vendor/github.com/hashicorp/nomad/helper/funcs.go
generated
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/hcl/hcl/ast"
|
||||
)
|
||||
|
||||
// validUUID is used to check if a given string looks like a UUID
|
||||
var validUUID = regexp.MustCompile(`(?i)^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$`)
|
||||
|
||||
// IsUUID returns true if the given string is a valid UUID.
|
||||
func IsUUID(str string) bool {
|
||||
const uuidLen = 36
|
||||
if len(str) != uuidLen {
|
||||
return false
|
||||
}
|
||||
|
||||
return validUUID.MatchString(str)
|
||||
}
|
||||
|
||||
// HashUUID takes an input UUID and returns a hashed version of the UUID to
|
||||
// ensure it is well distributed.
|
||||
func HashUUID(input string) (output string, hashed bool) {
|
||||
if !IsUUID(input) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Hash the input
|
||||
buf := sha512.Sum512([]byte(input))
|
||||
output = fmt.Sprintf("%08x-%04x-%04x-%04x-%12x",
|
||||
buf[0:4],
|
||||
buf[4:6],
|
||||
buf[6:8],
|
||||
buf[8:10],
|
||||
buf[10:16])
|
||||
|
||||
return output, true
|
||||
}
|
||||
|
||||
// boolToPtr returns the pointer to a boolean
|
||||
func BoolToPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
// IntToPtr returns the pointer to an int
|
||||
func IntToPtr(i int) *int {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Int64ToPtr returns the pointer to an int
|
||||
func Int64ToPtr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// UintToPtr returns the pointer to an uint
|
||||
func Uint64ToPtr(u uint64) *uint64 {
|
||||
return &u
|
||||
}
|
||||
|
||||
// StringToPtr returns the pointer to a string
|
||||
func StringToPtr(str string) *string {
|
||||
return &str
|
||||
}
|
||||
|
||||
// TimeToPtr returns the pointer to a time stamp
|
||||
func TimeToPtr(t time.Duration) *time.Duration {
|
||||
return &t
|
||||
}
|
||||
|
||||
func IntMin(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func IntMax(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func Uint64Max(a, b uint64) uint64 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// MapStringStringSliceValueSet returns the set of values in a map[string][]string
|
||||
func MapStringStringSliceValueSet(m map[string][]string) []string {
|
||||
set := make(map[string]struct{})
|
||||
for _, slice := range m {
|
||||
for _, v := range slice {
|
||||
set[v] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
flat := make([]string, 0, len(set))
|
||||
for k := range set {
|
||||
flat = append(flat, k)
|
||||
}
|
||||
return flat
|
||||
}
|
||||
|
||||
func SliceStringToSet(s []string) map[string]struct{} {
|
||||
m := make(map[string]struct{}, (len(s)+1)/2)
|
||||
for _, k := range s {
|
||||
m[k] = struct{}{}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// SliceStringIsSubset returns whether the smaller set of strings is a subset of
|
||||
// the larger. If the smaller slice is not a subset, the offending elements are
|
||||
// returned.
|
||||
func SliceStringIsSubset(larger, smaller []string) (bool, []string) {
|
||||
largerSet := make(map[string]struct{}, len(larger))
|
||||
for _, l := range larger {
|
||||
largerSet[l] = struct{}{}
|
||||
}
|
||||
|
||||
subset := true
|
||||
var offending []string
|
||||
for _, s := range smaller {
|
||||
if _, ok := largerSet[s]; !ok {
|
||||
subset = false
|
||||
offending = append(offending, s)
|
||||
}
|
||||
}
|
||||
|
||||
return subset, offending
|
||||
}
|
||||
|
||||
func SliceSetDisjoint(first, second []string) (bool, []string) {
|
||||
contained := make(map[string]struct{}, len(first))
|
||||
for _, k := range first {
|
||||
contained[k] = struct{}{}
|
||||
}
|
||||
|
||||
offending := make(map[string]struct{})
|
||||
for _, k := range second {
|
||||
if _, ok := contained[k]; ok {
|
||||
offending[k] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
if len(offending) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
flattened := make([]string, 0, len(offending))
|
||||
for k := range offending {
|
||||
flattened = append(flattened, k)
|
||||
}
|
||||
return false, flattened
|
||||
}
|
||||
|
||||
// Helpers for copying generic structures.
|
||||
func CopyMapStringString(m map[string]string) map[string]string {
|
||||
l := len(m)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make(map[string]string, l)
|
||||
for k, v := range m {
|
||||
c[k] = v
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func CopyMapStringStruct(m map[string]struct{}) map[string]struct{} {
|
||||
l := len(m)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make(map[string]struct{}, l)
|
||||
for k := range m {
|
||||
c[k] = struct{}{}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func CopyMapStringInt(m map[string]int) map[string]int {
|
||||
l := len(m)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make(map[string]int, l)
|
||||
for k, v := range m {
|
||||
c[k] = v
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func CopyMapStringFloat64(m map[string]float64) map[string]float64 {
|
||||
l := len(m)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make(map[string]float64, l)
|
||||
for k, v := range m {
|
||||
c[k] = v
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// CopyMapStringSliceString copies a map of strings to string slices such as
|
||||
// http.Header
|
||||
func CopyMapStringSliceString(m map[string][]string) map[string][]string {
|
||||
l := len(m)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make(map[string][]string, l)
|
||||
for k, v := range m {
|
||||
c[k] = CopySliceString(v)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func CopySliceString(s []string) []string {
|
||||
l := len(s)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]string, l)
|
||||
for i, v := range s {
|
||||
c[i] = v
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func CopySliceInt(s []int) []int {
|
||||
l := len(s)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]int, l)
|
||||
for i, v := range s {
|
||||
c[i] = v
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// CleanEnvVar replaces all occurrences of illegal characters in an environment
|
||||
// variable with the specified byte.
|
||||
func CleanEnvVar(s string, r byte) string {
|
||||
b := []byte(s)
|
||||
for i, c := range b {
|
||||
switch {
|
||||
case c == '_':
|
||||
case c == '.':
|
||||
case c >= 'a' && c <= 'z':
|
||||
case c >= 'A' && c <= 'Z':
|
||||
case i > 0 && c >= '0' && c <= '9':
|
||||
default:
|
||||
// Replace!
|
||||
b[i] = r
|
||||
}
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func CheckHCLKeys(node ast.Node, valid []string) error {
|
||||
var list *ast.ObjectList
|
||||
switch n := node.(type) {
|
||||
case *ast.ObjectList:
|
||||
list = n
|
||||
case *ast.ObjectType:
|
||||
list = n.List
|
||||
default:
|
||||
return fmt.Errorf("cannot check HCL keys of type %T", n)
|
||||
}
|
||||
|
||||
validMap := make(map[string]struct{}, len(valid))
|
||||
for _, v := range valid {
|
||||
validMap[v] = struct{}{}
|
||||
}
|
||||
|
||||
var result error
|
||||
for _, item := range list.Items {
|
||||
key := item.Keys[0].Token.Value().(string)
|
||||
if _, ok := validMap[key]; !ok {
|
||||
result = multierror.Append(result, fmt.Errorf(
|
||||
"invalid key: %s", key))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
58
vendor/github.com/hashicorp/nomad/helper/testlog/testlog.go
generated
vendored
Normal file
58
vendor/github.com/hashicorp/nomad/helper/testlog/testlog.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Package testlog creates a *log.Logger backed by *testing.T to ease logging
|
||||
// in tests. This allows logs from components being tested to only be printed
|
||||
// if the test fails (or the verbose flag is specified).
|
||||
package testlog
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
// UseStdout returns true if NOMAD_TEST_STDOUT=1 and sends logs to stdout.
|
||||
func UseStdout() bool {
|
||||
return os.Getenv("NOMAD_TEST_STDOUT") == "1"
|
||||
}
|
||||
|
||||
// LogPrinter is the methods of testing.T (or testing.B) needed by the test
|
||||
// logger.
|
||||
type LogPrinter interface {
|
||||
Logf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// writer implements io.Writer on top of a Logger.
|
||||
type writer struct {
|
||||
t LogPrinter
|
||||
}
|
||||
|
||||
// Write to an underlying Logger. Never returns an error.
|
||||
func (w *writer) Write(p []byte) (n int, err error) {
|
||||
w.t.Logf(string(p))
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// NewWriter creates a new io.Writer backed by a Logger.
|
||||
func NewWriter(t LogPrinter) io.Writer {
|
||||
if UseStdout() {
|
||||
return os.Stdout
|
||||
}
|
||||
return &writer{t}
|
||||
}
|
||||
|
||||
// New returns a new test logger. See https://golang.org/pkg/log/#New
|
||||
func New(t LogPrinter, prefix string, flag int) *log.Logger {
|
||||
if UseStdout() {
|
||||
return log.New(os.Stdout, prefix, flag)
|
||||
}
|
||||
return log.New(&writer{t}, prefix, flag)
|
||||
}
|
||||
|
||||
// WithPrefix returns a new test logger with the Lmicroseconds flag set.
|
||||
func WithPrefix(t LogPrinter, prefix string) *log.Logger {
|
||||
return New(t, prefix, log.Lmicroseconds)
|
||||
}
|
||||
|
||||
// NewLog logger with "TEST" prefix and the Lmicroseconds flag.
|
||||
func Logger(t LogPrinter) *log.Logger {
|
||||
return WithPrefix(t, "")
|
||||
}
|
||||
21
vendor/github.com/hashicorp/nomad/helper/uuid/uuid.go
generated
vendored
Normal file
21
vendor/github.com/hashicorp/nomad/helper/uuid/uuid.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package uuid
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Generate is used to generate a random UUID
|
||||
func Generate() string {
|
||||
buf := make([]byte, 16)
|
||||
if _, err := crand.Read(buf); err != nil {
|
||||
panic(fmt.Errorf("failed to read random bytes: %v", err))
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x",
|
||||
buf[0:4],
|
||||
buf[4:6],
|
||||
buf[6:8],
|
||||
buf[8:10],
|
||||
buf[10:16])
|
||||
}
|
||||
Reference in New Issue
Block a user