github.com/hugorut/terraform@v1.1.3/website/docs/language/functions/defaults.mdx (about) 1 --- 2 page_title: defaults - Functions - Configuration Language 3 description: The defaults function can fill in default values in place of null values. 4 --- 5 6 # `defaults` Function 7 8 -> **Note:** This function is available only in Terraform 0.15 and later. 9 10 ~> **Experimental:** This function is part of 11 [the optional attributes experiment](/language/expressions/type-constraints#experimental-optional-object-type-attributes) 12 and is only available in modules where the `module_variable_optional_attrs` 13 experiment is explicitly enabled. 14 15 The `defaults` function is a specialized function intended for use with 16 input variables whose type constraints are object types or collections of 17 object types that include optional attributes. 18 19 When you define an attribute as optional and the caller doesn't provide an 20 explicit value for it, Terraform will set the attribute to `null` to represent 21 that it was omitted. If you want to use a placeholder value other than `null` 22 when an attribute isn't set, you can use the `defaults` function to concisely 23 assign default values only where an attribute value was set to `null`. 24 25 ``` 26 defaults(input_value, defaults) 27 ``` 28 29 The `defaults` function expects that the `input_value` argument will be the 30 value of an input variable with an exact [type constraint](/language/expressions/types) 31 (not containing `any`). The function will then visit every attribute in 32 the data structure, including attributes of nested objects, and apply the 33 default values given in the defaults object. 34 35 The interpretation of attributes in the `defaults` argument depends on what 36 type an attribute has in the `input_value`: 37 38 * **Primitive types** (`string`, `number`, `bool`): if a default value is given 39 then it will be used only if the `input_value`'s attribute of the same 40 name has the value `null`. The default value's type must match the input 41 value's type. 42 * **Structural types** (`object` and `tuple` types): Terraform will recursively 43 visit all of the attributes or elements of the nested value and repeat the 44 same defaults-merging logic one level deeper. The default value's type must 45 be of the same kind as the input value's type, and a default value for an 46 object type must only contain attribute names that appear in the input 47 value's type. 48 * **Collection types** (`list`, `map`, and `set` types): Terraform will visit 49 each of the collection elements in turn and apply defaults to them. In this 50 case the default value is only a single value to be applied to _all_ elements 51 of the collection, so it must have a type compatible with the collection's 52 element type rather than with the collection type itself. 53 54 The above rules may be easier to follow with an example. Consider the following 55 Terraform configuration: 56 57 ```hcl 58 terraform { 59 # Optional attributes and the defaults function are 60 # both experimental, so we must opt in to the experiment. 61 experiments = [module_variable_optional_attrs] 62 } 63 64 variable "storage" { 65 type = object({ 66 name = string 67 enabled = optional(bool) 68 website = object({ 69 index_document = optional(string) 70 error_document = optional(string) 71 }) 72 documents = map( 73 object({ 74 source_file = string 75 content_type = optional(string) 76 }) 77 ) 78 }) 79 } 80 81 locals { 82 storage = defaults(var.storage, { 83 # If "enabled" isn't set then it will default 84 # to true. 85 enabled = true 86 87 # The "website" attribute is required, but 88 # it's here to provide defaults for the 89 # optional attributes inside. 90 website = { 91 index_document = "index.html" 92 error_document = "error.html" 93 } 94 95 # The "documents" attribute has a map type, 96 # so the default value represents defaults 97 # to be applied to all of the elements in 98 # the map, not for the map itself. Therefore 99 # it's a single object matching the map 100 # element type, not a map itself. 101 documents = { 102 # If _any_ of the map elements omit 103 # content_type then this default will be 104 # used instead. 105 content_type = "application/octet-stream" 106 } 107 }) 108 } 109 110 output "storage" { 111 value = local.storage 112 } 113 ``` 114 115 To test this out, we can create a file `terraform.tfvars` to provide an example 116 value for `var.storage`: 117 118 ```hcl 119 storage = { 120 name = "example" 121 122 website = { 123 error_document = "error.txt" 124 } 125 documents = { 126 "index.html" = { 127 source_file = "index.html.tmpl" 128 content_type = "text/html" 129 } 130 "error.txt" = { 131 source_file = "error.txt.tmpl" 132 content_type = "text/plain" 133 } 134 "terraform.exe" = { 135 source_file = "terraform.exe" 136 } 137 } 138 } 139 ``` 140 141 The above value conforms to the variable's type constraint because it only 142 omits attributes that are declared as optional. Terraform will automatically 143 populate those attributes with the value `null` before evaluating anything 144 else, and then the `defaults` function in `local.storage` will substitute 145 default values for each of them. 146 147 The result of this `defaults` call would therefore be the following object: 148 149 ``` 150 storage = { 151 "documents" = tomap({ 152 "error.txt" = { 153 "content_type" = "text/plain" 154 "source_file" = "error.txt.tmpl" 155 } 156 "index.html" = { 157 "content_type" = "text/html" 158 "source_file" = "index.html.tmpl" 159 } 160 "terraform.exe" = { 161 "content_type" = "application/octet-stream" 162 "source_file" = "terraform.exe" 163 } 164 }) 165 "enabled" = true 166 "name" = "example" 167 "website" = { 168 "error_document" = "error.txt" 169 "index_document" = "index.html" 170 } 171 } 172 ``` 173 174 Notice that `enabled` and `website.index_document` were both populated directly 175 from the defaults. Notice also that the `"terraform.exe"` element of 176 `documents` had its `content_type` attribute populated from the `documents` 177 default, but the default value didn't need to predict that there would be an 178 element key `"terraform.exe"` because the default values apply equally to 179 all elements of the map where the optional attributes are `null`. 180 181 ## Using `defaults` elsewhere 182 183 The design of the `defaults` function depends on input values having 184 well-specified type constraints, so it can reliably recognize the difference 185 between similar types: maps vs. objects, lists vs. tuples. The type constraint 186 causes Terraform to convert the caller's value to conform to the constraint 187 and thus `defaults` can rely on the input to conform. 188 189 Elsewhere in the Terraform language it's typical to be less precise about 190 types, for example using the object construction syntax `{ ... }` to construct 191 values that will be used as if they are maps. Because `defaults` uses the 192 type information of `input_value`, an `input_value` that _doesn't_ originate 193 in an input variable will tend not to have an appropriate value type and will 194 thus not be interpreted as expected by `defaults`. 195 196 We recommend using `defaults` only with fully-constrained input variable values 197 in the first argument, so you can use the variable's type constraint to 198 explicitly distinguish between collection and structural types.