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.