Default values set a value for an attribute when the Terraform configuration does not provide one. In SDKv2, default
values are set via fields on an attribute's schema. In the Framework, you set default values via plan modification.
Refer to
Plan Modification - Attribute Plan Modification
in the Framework documentation for details.
This page explains how to migrate attribute defaults in SDKv2 to AttributePlanModifier in the Framework.
In SDKv2, default values are defined for a primitive attribute type (i.e., TypeBool, TypeFloat, TypeInt,
TypeString) by the Default field on the attribute's schema. Alternatively, the DefaultFunc function is used to
compute a default value for an attribute.
The following code shows a basic implementation of a default value for a primitive attribute type in SDKv2.
Remember the following differences between SDKv2 and the Framework when completing the migration.
In SDKv2, default values are set with the Default or DefaultFunc fields on an attribute's schema.Schema struct.
In the Framework, you must implement an attribute plan modifier to set default values.
The following examples show how to migrate portions of the tls
provider.
For a complete example, clone the
terraform-provider-tls repository and compare the resource_private_key.go file in
v3.4.0 with the file
after the migration.
The following example from the resource_private_key.go file shows the implementation of the Default field for the
rsa_bits attribute on the tls_private_key resource with SDKv2.
The following example from the attribute_plan_modifiers.go file implements the DefaultValue attribute plan modifier
that the rsa_bits attribute uses.
funcDefaultValue(v attr.Value) tfsdk.AttributePlanModifier {return&defaultValueAttributePlanModifier{v}}type defaultValueAttributePlanModifier struct{
DefaultValue attr.Value
}var_ tfsdk.AttributePlanModifier =(*defaultValueAttributePlanModifier)(nil)func(apm *defaultValueAttributePlanModifier)Description(ctx context.Context)string{/* ... */}func(apm *defaultValueAttributePlanModifier)MarkdownDescription(ctx context.Context)string{/* ... */}func(apm *defaultValueAttributePlanModifier)Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, res *tfsdk.ModifyAttributePlanResponse){// If the attribute configuration is not null, we are done hereif!req.AttributeConfig.IsNull(){return}// If the attribute plan is "known" and "not null", then a previous plan modifier in the sequence// has already been applied, and we don't want to interfere.if!req.AttributePlan.IsUnknown()&&!req.AttributePlan.IsNull(){return}
res.AttributePlan = apm.DefaultValue
}
funcDefaultValue(v attr.Value) tfsdk.AttributePlanModifier {return&defaultValueAttributePlanModifier{v}}type defaultValueAttributePlanModifier struct{ DefaultValue attr.Value
}var_ tfsdk.AttributePlanModifier =(*defaultValueAttributePlanModifier)(nil)func(apm *defaultValueAttributePlanModifier)Description(ctx context.Context)string{/* ... */}func(apm *defaultValueAttributePlanModifier)MarkdownDescription(ctx context.Context)string{/* ... */}func(apm *defaultValueAttributePlanModifier)Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, res *tfsdk.ModifyAttributePlanResponse){// If the attribute configuration is not null, we are done hereif!req.AttributeConfig.IsNull(){return}// If the attribute plan is "known" and "not null", then a previous plan modifier in the sequence// has already been applied, and we don't want to interfere.if!req.AttributePlan.IsUnknown()&&!req.AttributePlan.IsNull(){return} res.AttributePlan = apm.DefaultValue
}