github.com/hernad/nomad@v1.6.112/helper/pluginutils/hclspecutils/type_expr.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package hclspecutils 5 6 import ( 7 "fmt" 8 "reflect" 9 10 hcl "github.com/hashicorp/hcl/v2" 11 "github.com/zclconf/go-cty/cty" 12 "github.com/zclconf/go-cty/cty/function" 13 ) 14 15 var typeType = cty.Capsule("type", reflect.TypeOf(cty.NilType)) 16 17 var typeEvalCtx = &hcl.EvalContext{ 18 Variables: map[string]cty.Value{ 19 "string": wrapTypeType(cty.String), 20 "bool": wrapTypeType(cty.Bool), 21 "number": wrapTypeType(cty.Number), 22 "any": wrapTypeType(cty.DynamicPseudoType), 23 }, 24 Functions: map[string]function.Function{ 25 "list": function.New(&function.Spec{ 26 Params: []function.Parameter{ 27 { 28 Name: "element_type", 29 Type: typeType, 30 }, 31 }, 32 Type: function.StaticReturnType(typeType), 33 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 34 ety := unwrapTypeType(args[0]) 35 ty := cty.List(ety) 36 return wrapTypeType(ty), nil 37 }, 38 }), 39 "set": function.New(&function.Spec{ 40 Params: []function.Parameter{ 41 { 42 Name: "element_type", 43 Type: typeType, 44 }, 45 }, 46 Type: function.StaticReturnType(typeType), 47 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 48 ety := unwrapTypeType(args[0]) 49 ty := cty.Set(ety) 50 return wrapTypeType(ty), nil 51 }, 52 }), 53 "map": function.New(&function.Spec{ 54 Params: []function.Parameter{ 55 { 56 Name: "element_type", 57 Type: typeType, 58 }, 59 }, 60 Type: function.StaticReturnType(typeType), 61 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 62 ety := unwrapTypeType(args[0]) 63 ty := cty.Map(ety) 64 return wrapTypeType(ty), nil 65 }, 66 }), 67 "tuple": function.New(&function.Spec{ 68 Params: []function.Parameter{ 69 { 70 Name: "element_types", 71 Type: cty.List(typeType), 72 }, 73 }, 74 Type: function.StaticReturnType(typeType), 75 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 76 etysVal := args[0] 77 etys := make([]cty.Type, 0, etysVal.LengthInt()) 78 for it := etysVal.ElementIterator(); it.Next(); { 79 _, wrapEty := it.Element() 80 etys = append(etys, unwrapTypeType(wrapEty)) 81 } 82 ty := cty.Tuple(etys) 83 return wrapTypeType(ty), nil 84 }, 85 }), 86 "object": function.New(&function.Spec{ 87 Params: []function.Parameter{ 88 { 89 Name: "attribute_types", 90 Type: cty.Map(typeType), 91 }, 92 }, 93 Type: function.StaticReturnType(typeType), 94 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 95 atysVal := args[0] 96 atys := make(map[string]cty.Type) 97 for it := atysVal.ElementIterator(); it.Next(); { 98 nameVal, wrapAty := it.Element() 99 name := nameVal.AsString() 100 atys[name] = unwrapTypeType(wrapAty) 101 } 102 ty := cty.Object(atys) 103 return wrapTypeType(ty), nil 104 }, 105 }), 106 }, 107 } 108 109 func evalTypeExpr(expr hcl.Expression) (cty.Type, hcl.Diagnostics) { 110 result, diags := expr.Value(typeEvalCtx) 111 if result.IsNull() { 112 return cty.DynamicPseudoType, diags 113 } 114 if !result.Type().Equals(typeType) { 115 diags = append(diags, &hcl.Diagnostic{ 116 Severity: hcl.DiagError, 117 Summary: "Invalid type expression", 118 Detail: fmt.Sprintf("A type is required, not %s.", result.Type().FriendlyName()), 119 }) 120 return cty.DynamicPseudoType, diags 121 } 122 123 return unwrapTypeType(result), diags 124 } 125 126 func wrapTypeType(ty cty.Type) cty.Value { 127 return cty.CapsuleVal(typeType, &ty) 128 } 129 130 func unwrapTypeType(val cty.Value) cty.Type { 131 return *(val.EncapsulatedValue().(*cty.Type)) 132 }