Terraform
- Plugin Framework
- v1.16.x (latest)
- No versions of this document exist before v1.15.x. Click below to redirect to the version homepage.
- v1.15.x
- v1.14.x
- v1.13.x
- v1.12.x
- v1.11.x
- v1.10.x
- v1.9.x
- v1.8.x
- v1.7.x
- v1.6.x
- v1.5.x
- v1.4.x
- v1.3.x
- v1.2.x
- v1.1.x
- v1.0.x
- v0.17.x
- v0.16.x
- v0.15.x
- v0.14.x
- v0.13.x
- v0.12.x
- v0.11.x
- v0.10.x
- v0.9.x
- v0.8.x
Attribute Types
Attributes are the fields in a resource, data source, or provider. They hold the values that end up in state. Every attribute has an attribute type, which describes the constraints on the data the attribute can hold. When you access an attribute from the configuration, state, or plan, you are accessing attribute values, which are the actual data that was found in the configuration, state, or plan.
You can either use the built-in attribute type and value implementations or implement your own.
Null and Unknown Values
There are two values every attribute in Terraform can hold, regardless of their type: null and unknown.
Null
Null represents the absence of a Terraform value. It is usually encountered with optional attributes that the practitioner neglected to specify a value for, but can show up on any non-required attribute. Required attributes can never be null.
Unknown
Unknown represents a Terraform value that is not yet known. Terraform uses a graph of providers, resources, and data sources to do things in the right order, and when a provider, resource, or data source relies on a value from another provider, resource, or data source that has not been resolved yet, it represents that state by using the unknown value. For example:
resource "example_foo" "bar" {
hello = "world"
demo = true
}
resource "example_baz" "quux" {
foo_id = example_foo.bar.id
}
In the example above, example_baz.quux is relying on the id attribute of
example_foo.bar. The id attribute of example_foo.bar isn't known until
after the apply. The plan would list it as (known after apply). During the
plan phase, example_baz.quux would get an unknown value as the value for
foo_id.
Because they can result from interpolations in the practitioner's config, you have no control over what attributes may contain an unknown value. However, by the time a resource is expected to be created, read, updated, or deleted, only its computed attributes can be unknown. The rest are guaranteed to have known values (or be null).
Provider configuration values can be unknown, and providers should handle that situation, even if that means just returning an error.
Built-In Types and Values
A collection of attribute type and attribute value implementations is available
in the
types
package.
StringType and String
Strings are a UTF-8 encoded collection of bytes.
hello = "world"
They are used by specifying the types.StringType constant in your
tfsdk.Attribute's Type property, and are represented by a types.String
struct in config, state, and plan. The types.String struct has the following
properties:
Valuecontains the string's value as a Gostringtype.Nullis set totruewhen the string's value is null.Unknownis set totruewhen the string's value is unknown.
Int64Type and Int64
Int64 are 64-bit integer values, such as 1234.
hello = 1234
They are used by specifying the types.Int64Type constant in your
tfsdk.Attribute's Type property, and are represented by a types.Int64
struct in config, state, and plan. The types.Int64 struct has the following
properties:
Valuecontains the number's value as a Goint64type.Nullis set totruewhen the number's value is null.Unknownis set totruewhen the number's value is unknown.
For 64-bit floating point numbers, see Float64Type and
Float64. For generic number handling, see
NumberType and Number64.
Float64Type and Float64
Float64 are 64-bit floating point values, such as 1234.5.
hello = 1234.5
They are used by specifying the types.Float64Type constant in your
tfsdk.Attribute's Type property, and are represented by a types.Float64
struct in config, state, and plan. The types.Float64 struct has the following
properties:
Valuecontains the number's value as a Gofloat64type.Nullis set totruewhen the number's value is null.Unknownis set totruewhen the number's value is unknown.
For 64-bit integer numbers, see Int64Type and
Int64. For generic number handling, see
NumberType and Number64.
NumberType and Number
Numbers are numeric values, both whole values like 12 or fractional values
like 3.14.
hello = 123
They are used by specifying the types.NumberType constant in your
tfsdk.Attribute's Type property, and are represented by a types.Number
struct in config, state, and plan. The types.Number struct has the following
properties:
Valuecontains the number's value as a Go*big.Floattype.Nullis set totruewhen the number's value is null.Unknownis set totruewhen the number's value is unknown.
For 64-bit integer numbers, see Int64Type and
Int64. For 64-bit floating point numbers, see
Float64Type and Float64.
BoolType and Bool
Bools are boolean values that can either be true or false.
hello = true
They are used by specifying the types.BoolType constant in your
tfsdk.Attribute's Type property, and are represented by a types.Bool
struct in config, state, and plan. The types.Bool struct has the following
properties:
Valuecontains the boolean's value as a Gobooltype.Nullis set totruewhen the boolean's value is null.Unknownis set totruewhen the boolean's value is unknown.
ListType and List
Lists are ordered collections of other types. Their elements, the values inside the list, must all be of the same type.
hello = ["red", "blue", "green"]
They are used by specifying a types.ListType value in your
tfsdk.Attribute's Type property. You must specify an ElemType property
for your list, indicating what type the elements should be. Lists are
represented by a types.List struct in config, state, and plan. The
types.List struct has the following properties:
ElemTypewill always contain the same type as theElemTypeproperty of thetypes.ListTypethat created thetypes.List.Elemcontains a list of values, one for each element in the list. The values will all be of the value type produced by theElemTypefor the list.Nullis set totruewhen the entire list's value is null. Individual elements may still be null even if the list'sNullproperty isfalse.Unknownis set totruewhen the entire list's value is unknown. Individual elements may still be unknown even if the list'sUnknownproperty isfalse.
Elements of a types.List with a non-null, non-unknown value can be accessed
without using type assertions by using the types.List's ElementsAs
method,
which uses the same conversion rules as the Get methods described in Access
State, Config, and Plan.
For an unordered collection with uniqueness constraints, see SetType and
Set.
MapType and Map
Maps are unordered collections of other types with unique string indexes. Their elements, the values inside the map, must all be of the same type. The keys used to index the elements must be strings, but there are (theoretically) no limitations on what keys are acceptable or how many there can be.
hello = {
pi = 3.14
random = 4
"meaning of life" = 42
}
They are used by specifying a types.MapType value in your
tfsdk.Attribute's Type property. You must specify an ElemType property
for your map, indicating what type the elements should be. Maps are
represented by a types.Map struct in config, state, and plan. The
types.Map struct has the following properties:
ElemTypewill always contain the same type as theElemTypeproperty of thetypes.MapTypethat created thetypes.Map.Elemcontains a map of values, one for each element in the map. The keys will be the keys defined in the config, state, or plan, and the values will all be of the value type produced by theElemTypefor the map.Nullis set totruewhen the entire map's value is null. Individual elements may still be null even if the map'sNullproperty isfalse.Unknownis set totruewhen the entire map's value is unknown. Individual elements may still be unknown even if the map'sUnknownproperty isfalse.
Elements of a types.Map with a non-null, non-unknown value can be accessed
without using type assertions by using the types.Map's ElementsAs
method,
which uses the same conversion rules as the Get methods described in Access
State, Config, and Plan.
ObjectType and Object
Objects are unordered collections of other types with unique, pre-specified
attributes. The attributes have names represented by strings, and each
attribute can specify its own type, similar to a Go struct type. The
attributes and their types are considered part of the object's type; two
objects are not the same type unless they have the same attributes, and those
attributes have the same types.
hello = {
pi = 3.14
demo = true
color = "red"
}
They are used by specifying a types.ObjectType value in your
tfsdk.Attribute's Type property. You must specify an AttrTypes property
for your object, indicating a map of the attribute names and the types of those
attributes. Objects are represented by a types.Object struct in config,
state, and plan. The types.Object struct has the following properties:
AttrTypeswill always contain the same attribute names and associated types as theAttrTypesproperty of thetypes.ObjectTypethat created thetypes.Object.Attrscontains a map of attribute names to values. Each attribute is guaranteed to always be present in the map. The values will always be of the value type for that attribute in theAttrTypesof the object.Nullis set totruewhen the entire object's value is null. Individual attributes may still be null even if the object'sNullproperty is false.Unknownis set totruewhen the entire object's value is unknown. Individual attributes may still be unknown even if the object'sUnknownproperty isfalse.
A non-null, non-unknown types.Object value can be converted to a Go struct
without using type assertions by using the types.Object's As
method,
which uses the same conversion rules as the Get methods described in Access
State, Config, and Plan.
SetType and Set
Sets are unordered collections of other types. Their elements, the values inside the set, must all be of the same type and must be unique.
hello = ["red", "blue", "green"]
They are used by specifying a types.SetType value in your
tfsdk.Attribute's Type property. You must specify an ElemType property
for your set, indicating what type the elements should be. Sets are
represented by a types.Set struct in config, state, and plan. The
types.Set struct has the following properties:
ElemTypewill always contain the same type as theElemTypeproperty of thetypes.SetTypethat created thetypes.Set.Elemcontains a list of values, one for each element in the set. The values will all be of the value type produced by theElemTypefor the list. Each element must be unique.Nullis set totruewhen the entire set's value is null. Individual elements may still be null even if the set'sNullproperty isfalse.Unknownis set totruewhen the entire set's value is unknown. Individual elements may still be unknown even if the set'sUnknownproperty isfalse.
Elements of a types.Set with a non-null, non-unknown value can be accessed
without using type assertions by using the types.Set's ElementsAs
method,
which uses the same conversion rules as the Get methods described in Access
State, Config, and Plan.
For an ordered collection without uniqueness constraints, see ListType and
List.
Create Provider-Defined Types and Values
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.
Important: Specifying plan customization for attribute types is not yet supported, limiting their utility. Support is expected in the near future.
attr.Type Interface
Use the attr.Type
interface
to implement an attribute type. It tells Terraform about its constraints and tells the framework how to create new attribute values from the information Terraform supplies. attr.Type has the following methods.
| Method | Description |
|---|---|
TerraformType | Returns the tftypes.Type value that describes its type constraints. This is how Terraform will know what type of values it can accept. |
ValueFromTerraform | Returns an attribute value from the tftypes.Value that Terraform supplies, or to return an error if it cannot. This error should not be used for validation purposes, and is expected to indicate programmer error, not practitioner error. |
Equal | Returns true if the attribute type is considered equal to the passed attribute type. |
AttributePathStepper Interface
All attribute types must implement the tftypes.AttributePathStepper
interface,
so the framework can access element or attribute types using attribute paths.
Type-Specific Interfaces
| Case | Interface | Description |
|---|---|---|
| Elements of the same type | TypeWithElementType | Attribute types that contain elements of the same type, like maps and lists, are required to implement attr.TypeWithElementType, which adds WithElementType and ElementType methods to the attr.Type interface. WithElementType must return a copy of the attribute type, but with its element type set to the passed type. ElementType must return the attribute type's element type. |
| Elements of different types | TypeWithElementTypes | Attribute types that contain elements of differing types, like tuples, are required to implement the attr.TypeWithElementTypes, which adds WithElementTypes and ElementTypes methods to the attr.Type interface. WithElementTypes must return a copy of the attribute type, but with its element types set to the passed element types. ElementTypes must return the attribute type's element types. |
| Contain attributes | TypeWithAttributeTypes | Attribute types that contain attributes, like objects, are required to implement the attr.TypeWithAttributeTypes interface, which adds WithAttributeTypes and AttributeTypes methods to the attr.Type interface. WithAttributeTypes must return a copy of the attribute type, but with its attribute types set to the passed attribute types. AttributeTypes must return the attribute type's attribute types. |
attr.Value Interface
Use the attr.Value
interface
to implement an attribute value. It tells the framework how to express that
attribute value in a way that Terraform will understand. attr.Value has the
following methods.
| Method | Description |
|---|---|
ToTerraformValue | Returns a Go type that is valid input for tftypes.NewValue for the tftypes.Type specified by the attr.Type that creates the attr.Value. |
Equal | Returns true if the passed attribute value should be considered to the attribute value the method is being called on. The passed attribute value is not guaranteed to be of the same Go type. |