github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/jobspec/helper.go (about) 1 package jobspec 2 3 // These functions are copied from helper/funcs.go 4 // added here to avoid jobspec depending on any other package 5 6 import ( 7 "fmt" 8 "reflect" 9 "strings" 10 "time" 11 12 multierror "github.com/hashicorp/go-multierror" 13 "github.com/hashicorp/hcl/hcl/ast" 14 ) 15 16 // stringToPtr returns the pointer to a string 17 func stringToPtr(str string) *string { 18 return &str 19 } 20 21 // timeToPtr returns the pointer to a time.Duration. 22 func timeToPtr(t time.Duration) *time.Duration { 23 return &t 24 } 25 26 // boolToPtr returns the pointer to a boolean 27 func boolToPtr(b bool) *bool { 28 return &b 29 } 30 31 func checkHCLKeys(node ast.Node, valid []string) error { 32 var list *ast.ObjectList 33 switch n := node.(type) { 34 case *ast.ObjectList: 35 list = n 36 case *ast.ObjectType: 37 list = n.List 38 default: 39 return fmt.Errorf("cannot check HCL keys of type %T", n) 40 } 41 42 validMap := make(map[string]struct{}, len(valid)) 43 for _, v := range valid { 44 validMap[v] = struct{}{} 45 } 46 47 var result error 48 for _, item := range list.Items { 49 key := item.Keys[0].Token.Value().(string) 50 if _, ok := validMap[key]; !ok { 51 result = multierror.Append(result, fmt.Errorf( 52 "invalid key: %s", key)) 53 } 54 } 55 56 return result 57 } 58 59 // UnusedKeys returns a pretty-printed error if any `hcl:",unusedKeys"` is not empty 60 func unusedKeys(obj interface{}) error { 61 val := reflect.ValueOf(obj) 62 if val.Kind() == reflect.Ptr { 63 val = reflect.Indirect(val) 64 } 65 return unusedKeysImpl([]string{}, val) 66 } 67 68 func unusedKeysImpl(path []string, val reflect.Value) error { 69 stype := val.Type() 70 for i := 0; i < stype.NumField(); i++ { 71 ftype := stype.Field(i) 72 fval := val.Field(i) 73 tags := strings.Split(ftype.Tag.Get("hcl"), ",") 74 name := tags[0] 75 tags = tags[1:] 76 77 if fval.Kind() == reflect.Ptr { 78 fval = reflect.Indirect(fval) 79 } 80 81 // struct? recurse. Add the struct's key to the path 82 if fval.Kind() == reflect.Struct { 83 err := unusedKeysImpl(append([]string{name}, path...), fval) 84 if err != nil { 85 return err 86 } 87 continue 88 } 89 90 // Search the hcl tags for "unusedKeys" 91 unusedKeys := false 92 for _, p := range tags { 93 if p == "unusedKeys" { 94 unusedKeys = true 95 break 96 } 97 } 98 99 if unusedKeys { 100 ks, ok := fval.Interface().([]string) 101 if ok && len(ks) != 0 { 102 ps := "" 103 if len(path) > 0 { 104 ps = strings.Join(path, ".") + " " 105 } 106 return fmt.Errorf("%sunexpected keys %s", 107 ps, 108 strings.Join(ks, ", ")) 109 } 110 } 111 } 112 return nil 113 }