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  }