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