List Nested Block
Tip
Use nested attribute types instead of block types for new schema implementations. Block support is mainly for migrating legacy SDK-based providers.
List nested blocks are an ordered collection of structures mapping explicit attribute names to nested attribute and block definitions. Values are represented by a list type in the framework, containing object type of the mapped attributes and blocks.
In this Terraform configuration example, a list nested block named example_block
is set to an ordered collection of an object value of attr1
to "value1"
and attr2
to 123
and an object value of attr1
to "value2"
and attr2
to 456
:
resource "examplecloud_thing" "example" {
example_block {
attr1 = "value1"
attr2 = 123
}
example_block {
attr1 = "value2"
attr2 = 456
}
}
Schema Definition
Note
Blocks can only be defined on schemas or nested blocks within a schema, not underneath an attribute or nested attribute.
Use one of the following block types to directly add a list nested value to a schema or block type:
Schema Type | Attribute Type |
---|---|
Data Source | schema.ListNestedBlock |
Provider | schema.ListNestedBlock |
Resource | schema.ListNestedBlock |
The NestedObject
field must be defined, which represents the object value type of every element of the list.
In this example, a resource schema defines a top level list nested block named example_block
with a required string attribute named attr1
and optional integer attribute named attr2
:
func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Blocks: map[string]schema.Block{
"example_block": schema.ListNestedBlock{
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"attr1": schema.StringAttribute{
Required: true,
// ... potentially other fields ...
},
"attr2": schema.Int64Attribute{
Optional: true,
// ... potentially other fields ...
},
},
},
// ... potentially other fields ...
},
// ... potentially other blocks ...
},
}
}
Its value type would be represented as types.List
of types.Object
with a mapping of attr1
to types.String
and attr2
to types.Int64
.
A block type may itself contain further collection or nested attribute/block types, if necessary.
In this example, a resource schema defines a top level list nested block named example_block
with a required list of strings attribute named attr
and a single nested block named block
:
func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Blocks: map[string]schema.Block{
"example_block": schema.ListNestedBlock{
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"attr": schema.ListAttribute{
ElementType: types.StringType,
Required: true,
// ... potentially other fields ...
},
},
Blocks: map[string]schema.Block{
"block": schema.ListNestedBlock{ /* ... */ },
},
},
// ... potentially other fields ...
},
// ... potentially other blocks ...
},
}
}
Its value type would be represented as a types.List
of types.Object
with a mapping of attr
to types.List
of types.String
and block
to types.Object
.
Custom Types
You may want to build your own attribute value and type implementations to allow your provider to combine validation, description, and plan customization behaviors into a reusable bundle. This helps avoid duplication or reimplementation and ensures consistency. These implementations use the CustomType
field in the attribute type.
Refer to Custom Types for further details on creating provider-defined types and values.
Deprecation
Set the DeprecationMessage
field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework deprecations documentation fully describes the recommended practices for deprecating an attribute or resource.
Some practitioner-focused examples of a deprecation message include:
- Configure
other_attribute
instead. This attribute will be removed in the next major version of the provider. - Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider.
Description
The framework provides two description fields, Description
and MarkdownDescription
, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, terraform-plugin-docs
for automated provider documentation generation and terraform-ls
for Terraform configuration editor integrations.
Plan Modification
Tip
Only managed resources implement this concept.
The framework provides two plan modification fields for managed resource attributes, Default
and PlanModifiers
, which define resource and attribute value planning behaviors. The resource default and plan modification documentation covers these features more in-depth.
Common Use Case Plan Modification
The listdefault
package defines common use case Default
implementations:
StaticValue(types.List)
: Define a static list default value for the attribute.
The listplanmodifier
package defines common use case PlanModifiers
implementations:
RequiresReplace()
: Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value.RequiresReplaceIf()
: Similar toRequiresReplace()
, but also checks if a given function returns true.RequiresReplaceIfConfigured()
: Similar toRequiresReplace()
, but also checks if the configuration value is not null.UseStateForUnknown()
: Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update.
Validation
Set the Validators
field to define validation. This validation logic is ran in addition to any validation contained within a custom type.
Common Use Case Validators
HashiCorp provides the additional terraform-plugin-framework-validators
Go module which contains validation logic for common use cases. The listvalidator
package within that module has list attribute validators such as defining conflicting attributes.
Accessing Values
The accessing values documentation covers general methods for reading schema (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The list type documentation covers methods for interacting with the attribute value itself.
Setting Values
The list type documentation covers methods for creating or setting the appropriate value. The writing data documentation covers general methods for writing schema (plan and state) data, which is necessary afterwards.