github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/configs/configschema/implied_type.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package configschema 5 6 import ( 7 "github.com/hashicorp/hcl/v2/hcldec" 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 // ImpliedType returns the cty.Type that would result from decoding a 12 // configuration block using the receiving block schema. 13 // 14 // The type returned from Block.ImpliedType differs from the type returned by 15 // hcldec.ImpliedType in that there will be no objects with optional 16 // attributes, since this value is not to be used for the decoding of 17 // configuration. 18 // 19 // ImpliedType always returns a result, even if the given schema is 20 // inconsistent. Code that creates configschema.Block objects should be 21 // tested using the InternalValidate method to detect any inconsistencies 22 // that would cause this method to fall back on defaults and assumptions. 23 func (b *Block) ImpliedType() cty.Type { 24 return b.specType().WithoutOptionalAttributesDeep() 25 } 26 27 // specType returns the cty.Type used for decoding a configuration 28 // block using the receiving block schema. This is the type used internally by 29 // hcldec to decode configuration. 30 func (b *Block) specType() cty.Type { 31 if b == nil { 32 return cty.EmptyObject 33 } 34 35 return hcldec.ImpliedType(b.DecoderSpec()) 36 } 37 38 // ContainsSensitive returns true if any of the attributes of the receiving 39 // block or any of its descendent blocks are marked as sensitive. 40 // 41 // Blocks themselves cannot be sensitive as a whole -- sensitivity is a 42 // per-attribute idea -- but sometimes we want to include a whole object 43 // decoded from a block in some UI output, and that is safe to do only if 44 // none of the contained attributes are sensitive. 45 func (b *Block) ContainsSensitive() bool { 46 for _, attrS := range b.Attributes { 47 if attrS.Sensitive { 48 return true 49 } 50 if attrS.NestedType != nil && attrS.NestedType.ContainsSensitive() { 51 return true 52 } 53 } 54 for _, blockS := range b.BlockTypes { 55 if blockS.ContainsSensitive() { 56 return true 57 } 58 } 59 return false 60 } 61 62 // ImpliedType returns the cty.Type that would result from decoding a Block's 63 // ImpliedType and getting the resulting AttributeType. 64 // 65 // ImpliedType always returns a result, even if the given schema is 66 // inconsistent. Code that creates configschema.Object objects should be tested 67 // using the InternalValidate method to detect any inconsistencies that would 68 // cause this method to fall back on defaults and assumptions. 69 func (a *Attribute) ImpliedType() cty.Type { 70 if a.NestedType != nil { 71 return a.NestedType.specType().WithoutOptionalAttributesDeep() 72 } 73 return a.Type 74 } 75 76 // ImpliedType returns the cty.Type that would result from decoding a 77 // NestedType Attribute using the receiving block schema. 78 // 79 // ImpliedType always returns a result, even if the given schema is 80 // inconsistent. Code that creates configschema.Object objects should be tested 81 // using the InternalValidate method to detect any inconsistencies that would 82 // cause this method to fall back on defaults and assumptions. 83 func (o *Object) ImpliedType() cty.Type { 84 return o.specType().WithoutOptionalAttributesDeep() 85 } 86 87 // specType returns the cty.Type used for decoding a NestedType Attribute using 88 // the receiving block schema. 89 func (o *Object) specType() cty.Type { 90 if o == nil { 91 return cty.EmptyObject 92 } 93 94 attrTys := make(map[string]cty.Type, len(o.Attributes)) 95 for name, attrS := range o.Attributes { 96 if attrS.NestedType != nil { 97 attrTys[name] = attrS.NestedType.specType() 98 } else { 99 attrTys[name] = attrS.Type 100 } 101 } 102 optAttrs := listOptionalAttrsFromObject(o) 103 104 var ret cty.Type 105 if len(optAttrs) > 0 { 106 ret = cty.ObjectWithOptionalAttrs(attrTys, optAttrs) 107 } else { 108 ret = cty.Object(attrTys) 109 } 110 switch o.Nesting { 111 case NestingSingle: 112 return ret 113 case NestingList: 114 return cty.List(ret) 115 case NestingMap: 116 return cty.Map(ret) 117 case NestingSet: 118 return cty.Set(ret) 119 default: // Should never happen 120 return cty.EmptyObject 121 } 122 } 123 124 // ContainsSensitive returns true if any of the attributes of the receiving 125 // Object are marked as sensitive. 126 func (o *Object) ContainsSensitive() bool { 127 for _, attrS := range o.Attributes { 128 if attrS.Sensitive { 129 return true 130 } 131 if attrS.NestedType != nil && attrS.NestedType.ContainsSensitive() { 132 return true 133 } 134 } 135 return false 136 }