Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
template: move jobspec parsing into Levant to avoid dep hell.
The Nomad module setup is not designed nor intended to have any pkg apart from api imported. This caused problems when using the jobspec package. The Nomad Terraform provider has exactly this problem and has its own version of the Parse functionality. I attempted to import this to avoid more duplication but ran into hashicorp/terraform-provider-nomad#150. This is therefore a temp solution so the project can be easily used and released.
- Loading branch information
Showing
12 changed files
with
3,191 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package helper | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"strings" | ||
"time" | ||
|
||
multierror "github.com/hashicorp/go-multierror" | ||
"github.com/hashicorp/hcl/hcl/ast" | ||
) | ||
|
||
// boolToPtr returns the pointer to a boolean | ||
func BoolToPtr(b bool) *bool { | ||
return &b | ||
} | ||
|
||
// 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 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 | ||
} | ||
|
||
// UnusedKeys returns a pretty-printed error if any `hcl:",unusedKeys"` is not empty | ||
func UnusedKeys(obj interface{}) error { | ||
val := reflect.ValueOf(obj) | ||
if val.Kind() == reflect.Ptr { | ||
val = reflect.Indirect(val) | ||
} | ||
return unusedKeysImpl([]string{}, val) | ||
} | ||
|
||
func unusedKeysImpl(path []string, val reflect.Value) error { | ||
stype := val.Type() | ||
for i := 0; i < stype.NumField(); i++ { | ||
ftype := stype.Field(i) | ||
fval := val.Field(i) | ||
tags := strings.Split(ftype.Tag.Get("hcl"), ",") | ||
name := tags[0] | ||
tags = tags[1:] | ||
|
||
if fval.Kind() == reflect.Ptr { | ||
fval = reflect.Indirect(fval) | ||
} | ||
|
||
// struct? recurse. Add the struct's key to the path | ||
if fval.Kind() == reflect.Struct { | ||
err := unusedKeysImpl(append([]string{name}, path...), fval) | ||
if err != nil { | ||
return err | ||
} | ||
continue | ||
} | ||
|
||
// Search the hcl tags for "unusedKeys" | ||
unusedKeys := false | ||
for _, p := range tags { | ||
if p == "unusedKeys" { | ||
unusedKeys = true | ||
break | ||
} | ||
} | ||
|
||
if unusedKeys { | ||
ks, ok := fval.Interface().([]string) | ||
if ok && len(ks) != 0 { | ||
ps := "" | ||
if len(path) > 0 { | ||
ps = strings.Join(path, ".") + " " | ||
} | ||
return fmt.Errorf("%sunexpected keys %s", | ||
ps, | ||
strings.Join(ks, ", ")) | ||
} | ||
} | ||
} | ||
return nil | ||
} |
Oops, something went wrong.