Terraform
Default
After validation and before applying configuration changes, Terraform generates a plan that describes the expected values and behaviors of those changes. Resources can then tailor the plan to set default values on computed resource attributes that are null in the configuration.
A Default can only be added to a resource schema attribute.
When is a Default set?
A Default is set during the planning process, immediately prior to the framework marking computed attributes that are null in the configuration as unknown in the plan.
Attribute Default
You can supply the attribute type Default
field with a default for that attribute. For example:
// Typically within the schema.Schema returned by Schema() for a resource.
schema.StringAttribute{
// ... other Attribute configuration ...
Default: stringdefault.StaticString("str"),
}
schema.SetAttribute{
// ... other Attribute configuration ...
Default: setdefault.StaticValue(
types.SetValueMust(
types.StringType,
[]attr.Value{
types.StringValue("str"),
},
),
),
},
If defined, a default is applied to the current attribute providing that the attribute is null in the configuration. If any nested attributes define a default, then those are applied afterwards. Any default that returns an error will prevent Terraform from applying further defaults of that attribute as well as any nested attribute defaults.
Common Use Case Attribute Defaults
The framework implements static value defaults in the typed packages under resource/schema/
:
Custom Default Implementations
To create an attribute default, you must implement the one of the resource/schema/defaults
package interfaces. For example:
// timeDefaultValue is a default that sets the value for a types.StringType
// attribute to the current time when it is not configured. The attribute
// must be marked as Optional and Computed. When setting the state during
// the resource Create, Read, or Update methods, this value must also be
// included or the Terraform CLI will generate an error.
type timeDefaultValue struct {
time time.Time
}
// Description returns a plain text description of the default's behavior, suitable for a practitioner to understand its impact.
func (d timeDefaultValue) Description(ctx context.Context) string {
return fmt.Sprintf("If value is not configured, defaults to a string representation of the current time")
}
// MarkdownDescription returns a markdown formatted description of the default's behavior, suitable for a practitioner to understand its impact.
func (d timeDefaultValue) MarkdownDescription(ctx context.Context) string {
return fmt.Sprintf("If value is not configured, defaults to a string representation of the current time")
}
// DefaultString runs the logic of the default. Access to the path is available in `req`, while
// `resp` contains fields for updating the planned value, and returning diagnostics.
func (d timeDefaultValue) DefaultString(_ context.Context, req defaults.StringRequest, resp *defaults.StringResponse) {
resp.PlanValue = types.StringValue(d.time.Format(time.RFC3339))
}
Optionally, you may also want to create a helper function to instantiate the default. For example:
func timeDefault(t time.Time) defaults.String {
return timeDefaultValue{
time: t,
}
}