Terraform
Schema Attributes and Types
Almost every Terraform Plugin offers user configurable parameters, examples such
as a Provider’s region
or a Resource's name
. Each parameter is defined in
the items schema, which is a map of string names to schema structs.
In the below example implementation of a Resource you see parameters uuid
and
name
defined:
func resourceExampleResource() *schema.Resource {
return &schema.Resource{
// ... //
Schema: map[string]*schema.Schema{
"uuid": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateName,
},
// ... //
},
}
}
The Schema attribute Type
defines what kind of values users can provide in
their configuration for this element. Here we define the available schema types
supported. See Schema Behaviors
for more information on configuring element behaviors.
Types
The schema attribute Type
determines what data is valid in configuring the
element, as well as the type of data returned when used in an
expression. Schemas attributes must
be one of the types defined below, and can be loosely categorized as either
Primitive or Aggregate types:
Primitive types
Primitive types are simple values such as integers, booleans, and strings.
Primitives are stored in the
state file as "key": "value"
string pairs, where both key
and value
are string representations.
Aggregate types
Aggregate types form more complicated data types by combining primitive types.
Aggregate types may define the types of elements they contain by using the
Elem
property. If the Elem
property is omitted, the default element data
type is a string
.
Aggregate types are stored in state as a key.index
and value
pair for each
element of the property, with a unique index
appended to the key
based on
the type. There is an additional key.index
item included in the state that
tracks the number of items the property contains.
Primitive Types
TypeBool
Data structure: bool
Example: true
or false
Schema example:
"encrypted": {
Type: schema.TypeBool,
},
Configuration example:
resource "example_volume" "ex" {
encrypted = true
}
State representation:
"encrypted": "true",
TypeInt
Data structure: int
Example: -9
, 0
, 1
, 2
, 9
Schema example:
"cores": {
Type: schema.TypeInt,
},
Configuration example:
resource "example_compute_instance" "ex" {
cores = 16
}
State representation:
"cores": "16",
TypeFloat
Data structure: float64
Example: 1.0
, 7.19009
Schema example:
"price": {
Type: schema.TypeFloat,
},
Configuration example:
resource "example_spot_request" "ex" {
price = 0.37
}
State representation:
"price": "0.37",
TypeString
Data structure: string
Example: "Hello, world!"
Schema example:
"name": {
Type: schema.TypeString,
},
Configuration example:
resource "example_spot_request" "ex" {
description = "Managed by Terraform"
}
State representation:
"description": "Managed by Terraform",
Date & Time Data
TypeString
is also used for date/time data, the preferred format is RFC 3339 (you can use the provided validation function).
Example: 2006-01-02T15:04:05+07:00
Schema example:
"expiration": {
Type: schema.TypeString,
ValidateFunc: validation.IsRFC3339Time,
},
Configuration example:
resource "example_resource" "ex" {
expiration = "2006-01-02T15:04:05+07:00"
}
State representation:
"expiration": "2006-01-02T15:04:05+07:00",
Aggregate Types
TypeMap
Data structure: map: map[string]any
Example: key = value
A key based map (also known as a dictionary) with string keys and values defined
by the Elem
property.
NOTE: Using the Elem
block to define specific keys for the map is currently not possible. A potential workaround would be to confirm the required keys are set when expanding the Map object inside the resource code.
Schema example:
"tags": {
Type: schema.TypeMap,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
Configuration example:
resource "example_compute_instance" "ex" {
tags {
env = "development"
name = "example tag"
}
}
State representation:
TypeMap
items are stored in state with the key as the index. The count of
items in a map is denoted by the %
index:
"tags.%": "2",
"tags.env": "development",
"tags.name": "example tag",
TypeList
Data structure: Slice: []any
Example: []interface{"2", "3", "4"}
Used to represent an ordered collection of items, where the order the items
are presented can impact the behavior of the resource being modeled. An example
of ordered items would be network routing rules, where rules are examined in the
order they are given until a match is found. The items are all of the same type
defined by the Elem
property.
Schema example:
"termination_policies": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
Configuration example:
resource "example_compute_instance" "ex" {
termination_policies = ["OldestInstance","ClosestToNextInstanceHour"]
}
State representation:
TypeList
items are stored in state in a zero based index data structure.
"name_servers.#": "4",
"name_servers.0": "ns-1508.awsdns-60.org",
"name_servers.1": "ns-1956.awsdns-52.co.uk",
"name_servers.2": "ns-469.awsdns-58.com",
"name_servers.3": "ns-564.awsdns-06.net",
TypeSet
Data structure: *schema.Set
Example: []string{"one", "two", "three"}
TypeSet
implements set behavior and is used to represent an unordered
collection of items, meaning that their ordering specified does not need to be
consistent, and the ordering itself has no impact on the behavior of the
resource.
The elements of a set can be any of the other types allowed by Terraform,
including another schema
. Set items cannot be repeated.
Schema example:
"ingress": {
Type: schema.TypeSet,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"from_port": {
Type: schema.TypeInt,
Required: true,
},
"to_port": {
Type: schema.TypeInt,
Required: true,
},
"protocol": {
Type: schema.TypeString,
Required: true,
StateFunc: protocolStateFunc,
},
"cidr_blocks": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
}
Configuration example:
resource "example_security_group" "ex" {
name = "sg_test"
description = "managed by Terraform"
ingress {
protocol = "tcp"
from_port = 80
to_port = 9000
cidr_blocks = ["10.0.0.0/8"]
}
ingress {
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["0.0.0.0/0", "10.0.0.0/8"]
}
}
State representation:
TypeSet
items are stored in state with an index value calculated by the hash
of the attributes of the set.
"ingress.#": "2",
"ingress.1061987227.cidr_blocks.#": "1",
"ingress.1061987227.cidr_blocks.0": "10.0.0.0/8",
"ingress.1061987227.description": "",
"ingress.1061987227.from_port": "80",
"ingress.1061987227.ipv6_cidr_blocks.#": "0",
"ingress.1061987227.protocol": "tcp",
"ingress.1061987227.security_groups.#": "0",
"ingress.1061987227.self": "false",
"ingress.1061987227.to_port": "9000",
"ingress.493694946.cidr_blocks.#": "2",
"ingress.493694946.cidr_blocks.0": "0.0.0.0/0",
"ingress.493694946.cidr_blocks.1": "10.0.0.0/8",
"ingress.493694946.description": "",
"ingress.493694946.from_port": "80",
"ingress.493694946.ipv6_cidr_blocks.#": "0",
"ingress.493694946.protocol": "tcp",
"ingress.493694946.security_groups.#": "0",
"ingress.493694946.self": "false",
"ingress.493694946.to_port": "8000",
Next Steps
Checkout Schema Behaviors to learn how to customize each schema elements behavior.