github.com/hartzell/terraform@v0.8.6-0.20180503104400-0cc9e050ecd4/config/configschema/decoder_spec.go (about) 1 package configschema 2 3 import ( 4 "github.com/hashicorp/hcl2/hcldec" 5 "github.com/zclconf/go-cty/cty" 6 ) 7 8 var mapLabelNames = []string{"key"} 9 10 // DecoderSpec returns a hcldec.Spec that can be used to decode a HCL Body 11 // using the facilities in the hcldec package. 12 // 13 // The returned specification is guaranteed to return a value of the same type 14 // returned by method ImpliedType, but it may contain null or unknown values if 15 // any of the block attributes are defined as optional and/or computed 16 // respectively. 17 func (b *Block) DecoderSpec() hcldec.Spec { 18 ret := hcldec.ObjectSpec{} 19 if b == nil { 20 return ret 21 } 22 23 for name, attrS := range b.Attributes { 24 switch { 25 case attrS.Computed && attrS.Optional: 26 // In this special case we use an unknown value as a default 27 // to get the intended behavior that the result is computed 28 // unless it has been explicitly set in config. 29 ret[name] = &hcldec.DefaultSpec{ 30 Primary: &hcldec.AttrSpec{ 31 Name: name, 32 Type: attrS.Type, 33 }, 34 Default: &hcldec.LiteralSpec{ 35 Value: cty.UnknownVal(attrS.Type), 36 }, 37 } 38 case attrS.Computed: 39 ret[name] = &hcldec.LiteralSpec{ 40 Value: cty.UnknownVal(attrS.Type), 41 } 42 default: 43 ret[name] = &hcldec.AttrSpec{ 44 Name: name, 45 Type: attrS.Type, 46 Required: attrS.Required, 47 } 48 } 49 } 50 51 for name, blockS := range b.BlockTypes { 52 if _, exists := ret[name]; exists { 53 // This indicates an invalid schema, since it's not valid to 54 // define both an attribute and a block type of the same name. 55 // However, we don't raise this here since it's checked by 56 // InternalValidate. 57 continue 58 } 59 60 childSpec := blockS.Block.DecoderSpec() 61 62 switch blockS.Nesting { 63 case NestingSingle: 64 ret[name] = &hcldec.BlockSpec{ 65 TypeName: name, 66 Nested: childSpec, 67 Required: blockS.MinItems == 1 && blockS.MaxItems >= 1, 68 } 69 case NestingList: 70 ret[name] = &hcldec.BlockListSpec{ 71 TypeName: name, 72 Nested: childSpec, 73 MinItems: blockS.MinItems, 74 MaxItems: blockS.MaxItems, 75 } 76 case NestingSet: 77 ret[name] = &hcldec.BlockSetSpec{ 78 TypeName: name, 79 Nested: childSpec, 80 MinItems: blockS.MinItems, 81 MaxItems: blockS.MaxItems, 82 } 83 case NestingMap: 84 ret[name] = &hcldec.BlockMapSpec{ 85 TypeName: name, 86 Nested: childSpec, 87 LabelNames: mapLabelNames, 88 } 89 default: 90 // Invalid nesting type is just ignored. It's checked by 91 // InternalValidate. 92 continue 93 } 94 } 95 96 return ret 97 }