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.