Terraform
Migrating blocks
This page explains how to migrate nested blocks that are not computed (i.e., do
not set Computed: true
) from SDKv2 to the framework. Refer to Blocks with
Computed
Fields
for more details about migrating nested blocks that contain fields that are
computed.
Background
Some providers, resources, and data sources include repeatable nested blocks in their attributes. These nested blocks typically represent separate objects that are related to (or embedded within) the containing object.
The following table describes the mapping between SDK Schema Fields and the framework.
SDK Schema Field | Framework |
---|---|
Type | ListNestedBlock, SetNestedBlock |
ConfigMode | Schema must be explictly defined using Attributes and Blocks |
Required | listvalidator.IsRequired, setvalidator.IsRequired |
Optional | N/A - no implementation required |
Computed | Blocks with Computed Fields |
ForceNew | RequiresReplace on PlanModifiers field on attribute within block or implementation of ResourceWithModifyPlan interface |
DiffSuppressFunc | PlanModifiers field on attribute within block or implementation of ResourceWithModifyPlan interface |
DiffSuppressOnRefresh | Read method on resource |
Description | Description field on block |
InputDefault | N/A - no longer valid |
StateFunc | Requires implementation of bespoke logic before storing state, for instance in resource Create method |
Elem | NestedObject within block |
MaxItems | Use listValidator.SizeAtMost or setvalidator.SizeAtMost on Validators field on ListNestedBlock or SetNestedBlock |
MinItems | Use listValidator.SizeAtLeast or setvalidator.SizeAtLeast on Validators field on ListNestedBlock or SetNestedBlock |
Set | N/A - no implementation required |
ComputedWhen | N/A - no longer valid |
ConflictsWith | Predefined Validators |
ExactlyOneOf | Predefined Validators |
AtLeastOneOf | Predefined Validators |
RequiredWith | Predefined Validators |
Deprecated | DeprecationMessage field on attribute within block |
ValidateFunc | Predefined Validators and Custom Validators |
ValidateDiagFunc | Predefined Validators and Custom Validators |
Sensitive | N/A - only supported on attributes |
Migrating nested blocks
To migrate a nested block to the framework, add it to your provider,
resource, or data source's schema. In the framework, nested blocks are defined
in the schema's Blocks
field.
The following example Terraform configuration shows a nested block in a
resource. The subject
nested block within the tls_cert_request
resource
configures the subject of a certificate request with the common_name
and
organization
attributes.
resource "tls_cert_request" "example" {
private_key_pem = file("private_key.pem")
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
}
The following example configuration shows an complex type attribute, not a nested block.
resource "examplecloud_thing" "example" {
example_attribute = {
"key1" = "one"
"key2" = "two"
}
}
Refer to Attributes - Available attribute types in the framework documentation for details about implementing complex types in the framework.
In SDKv2, blocks are defined by an attribute whose type is TypeList
or TypeSet
and whose Elem
field is set to a
schema.Resource
that contains a map of the block's attribute names to corresponding schemaSchema
structs.
In the framework, implement nested blocks with the Blocks
field of your
provider, resource, or data source's schema, as returned by the Schema
method.
The Blocks
field maps the name of each block to a schema.Block
definition.
The following example shows the implementation of a nested block with SDKv2.
SDKv2
func resourceExample() *schema.Resource {
return &schema.Resource{
/* ... */
map[string]*schema.Schema{
"example" = &schema.Schema{
Type: schema.TypeList,
Optional: bool,
MaxItems: int,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"nested_example": {
Type: schema.TypeString,
Optional: bool,
/* ... */
The following example shows how the block is defined with the framework after the migration.
Framework
func (r *ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
/* ... */
Blocks: map[string]schema.Block{
"example": schema.ListNestedBlock{
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"nested_example": schema.StringAttribute{
Optional: bool
/* ... */
Examples
The following examples show how to migrate nested blocks to the framework.
Nested block
To migrate a nested block to the framework, add it to the Blocks
key in your
schema.
The following example shows the implementation of the example_nested_block
nested block with SDKv2.
SDKv2
map[string]*schema.Schema{
"example_attribute": &schema.Schema{
Type: schema.TypeString,
/* ... */
"example_nested_block" = &schema.Schema{
Type: schema.TypeList,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"example_block_attribute_one": {
Type: schema.TypeString,
/* ... */
},
"example_block_attribute_two": {
Type: schema.TypeString,
/* ... */
},
/* ... */
The following example shows how the nested example_nested_block
block is
defined with the framework after the migration.
Framework
schema.Schema{
Attributes: map[string]schema.Attribute{
"example_attribute": schema.StringAttribute{
/* ... */
Blocks: map[string]schema.Block{
"example_nested_block": schema.ListNestedBlock{
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"example_block_attribute_one": schema.StringAttribute{
/* ... */
},
"example_block_attribute_two": schema.StringAttribute{
/* ... */
},
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},