github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/website/docs/configuration/attr-as-blocks.html.md (about) 1 --- 2 layout: "docs" 3 page_title: "Attributes as Blocks - Configuration Language" 4 sidebar_current: "docs-config-attr-as-blocks" 5 description: |- 6 For historical reasons, certain arguments within resource blocks can use either 7 block or attribute syntax. 8 --- 9 10 # Attributes as Blocks 11 12 -> **Note:** This page is an appendix to the Terraform documentation, and is 13 outside the normal navigation hierarchy. Most users do not need to know the full 14 details of the behavior described below. 15 16 ## Summary 17 18 Many resource types use repeatable nested blocks to manage collections of 19 sub-objects related to the primary resource. 20 21 Rarely, some resource types _also_ support an argument with the same name as a 22 nested block type, and will purge any sub-objects of that type if that argument 23 is set to an empty list (`<ATTR> = []`). 24 25 Most users do not need to know any further details of this "nested block or 26 empty list" behavior. However, read further if you need to: 27 28 - Use Terraform's [JSON syntax](/docs/configuration/syntax-json.html) with this 29 type of resource. 30 - Create a reusable module that wraps this type of resource. 31 32 ## Details 33 34 In Terraform v0.12 and later, the language makes a distinction between 35 [argument syntax and nested block syntax](/docs/configuration/syntax.html#arguments-and-blocks) 36 within blocks: 37 38 * Argument syntax sets a named argument for the containing object. If the 39 attribute has a default value then an explicitly-specified value entirely 40 overrides that default. 41 42 * Nested block syntax represents a related child object of the container that 43 has its own set of arguments. Where multiple such objects are possible, multiple 44 blocks of the same type can be present. If the nested attributes themselves 45 have default values, they are honored for each nested block separately, 46 merging in with any explicitly-defined arguments. 47 48 The distinction between these is particularly important for 49 [JSON syntax](/docs/configuration/syntax-json.html) 50 because the same primitive JSON constructs (lists and objects) will be 51 interpreted differently depending on whether a particular name is an argument 52 or a nested block type. 53 54 However, in some cases existing provider features were relying on the 55 conflation of these two concepts in the language of Terraform v0.11 and earlier, 56 using nested block syntax in most cases but using argument syntax to represent 57 explicitly the idea of removing all existing objects of that type, since the 58 absence of any blocks was interpreted as "ignore any existing objects". 59 60 The information on this page only applies to certain special arguments that 61 were relying on this usage pattern prior to Terraform v0.12. The documentation 62 for each of those features links to this page for details of the special usage 63 patterns that apply. In all other cases, use either argument or nested block 64 syntax as directed by the examples in the documentation for a particular 65 resource type. 66 67 ## Defining a Fixed Object Collection Value 68 69 When working with resource type arguments that behave in this way, it is valid 70 and we recommend to use the nested block syntax whenever defining a fixed 71 collection of objects: 72 73 ```hcl 74 example { 75 foo = "bar" 76 } 77 example { 78 foo = "baz" 79 } 80 ``` 81 82 The above implicitly specifies a two-element list of objects assigned to the 83 `example` argument, treating it as if it were a nested block type. 84 85 If you need to explicitly call for zero `example` objects, you must use the 86 argument syntax with an empty list: 87 88 ```hcl 89 example = [] 90 ``` 91 92 These two forms cannot be mixed; there cannot be both explicitly zero `example` 93 objects and explicit single `example` blocks declared at the same time. 94 95 For true nested blocks where this special behavior does not apply, assigning 96 `[]` using argument syntax is not valid. The normal way to specify zero objects 97 of a type is to write no nested blocks at all. 98 99 ## Arbitrary Expressions with Argument Syntax 100 101 Although we recommend using block syntax for simple cases for readability, the 102 names that work in this mode _are_ defined as arguments, and so it is possible 103 to use argument syntax to assign arbitrary dynamic expressions to them, as 104 long as the expression has the expected result type: 105 106 ```hcl 107 example = [ 108 for name in var.names: { 109 foo = name 110 } 111 ] 112 ``` 113 114 ```hcl 115 # Not recommended, but valid: a constant list-of-objects expression 116 example = [ 117 { 118 foo = "bar" 119 }, 120 { 121 foo = "baz" 122 }, 123 ] 124 ``` 125 126 Because of the rule that argument declarations like this fully override any 127 default value, when creating a list-of-objects expression directly the usual 128 handling of optional arguments does not apply, so all of the arguments must be 129 assigned a value, even if it's an explicit `null`: 130 131 ```hcl 132 example = [ 133 { 134 # Cannot omit foo in this case, even though it would be optional in the 135 # nested block syntax. 136 foo = null 137 }, 138 ] 139 ``` 140 141 If you are writing a reusable module that allows callers to pass in a list of 142 objects to assign to such an argument, you may wish to use the `merge` function 143 to populate any attributes the user didn't explicitly set, in order to give 144 the module user the effect of optional arguments: 145 146 ```hcl 147 example = [ 148 for ex in var.examples: merge({ 149 foo = null # (or any other suitable default value) 150 }, ex) 151 ] 152 ``` 153 154 For the arguments that use the attributes-as-blocks usage mode, the above is 155 a better pattern than using 156 [`dynamic` blocks](/docs/configuration/expressions.html#dynamic-blocks) 157 because the case where the 158 caller provides an empty list will result in explicitly assigning an empty 159 list value, rather than assigning no value at all and thus retaining and 160 ignoring any existing objects. `dynamic` blocks are required for 161 dynamically-generating _normal_ nested blocks, though. 162 163 ## In JSON syntax 164 165 Arguments that use this special mode are specified in JSON syntax always using 166 the [JSON expression mapping](/docs/configuration/syntax-json.html#expression-mapping) 167 to produce a list of objects. 168 169 The interpretation of these values in JSON syntax is, therefore, equivalent 170 to that described under _Arbitrary Expressions with Argument Syntax_ above, 171 but expressed in JSON syntax instead. 172 173 Due to the ambiguity of the JSON syntax, there is no way to distinguish based 174 on the input alone between argument and nested block usage, so the JSON syntax 175 cannot support the nested block processing mode for these arguments. This is, 176 unfortunately, one necessary concession on the equivalence between native syntax 177 and JSON syntax made pragmatically for compatibility with existing provider 178 design patterns. Providers may phase out such patterns in future major releases.