Skip to content

Commit 6228f97

Browse files
committed
Extracting "Conversion Rules" from "Acessing State" and "Writing State" into a separate page (#418)
1 parent c8a7082 commit 6228f97

File tree

4 files changed

+249
-231
lines changed

4 files changed

+249
-231
lines changed

website/data/plugin-framework-nav-data.json

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@
148148
{
149149
"title": "Writing Data",
150150
"path": "handling-data/writing-state"
151+
},
152+
{
153+
"title": "Conversion Rules",
154+
"path": "handling-data/conversion-rules"
151155
}
152156
]
153157
},
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
22
page_title: 'Plugin Development - Framework: Access State, Config, and Plan'
33
description: |-
4-
How to read values from state, config, and plan in the Terraform provider
5-
development framework.
4+
How to read values from state, config, and plan in the Terraform plugin
5+
framework.
66
---
77

88
# Accessing State, Config, and Plan
@@ -112,127 +112,5 @@ or null. It is safe to assume:
112112
In any other circumstances, the provider is responsible for handling the
113113
possibility that an unknown or null value may be presented to it.
114114

115-
## Conversion Rules
116-
117-
!> **Warning:** It can be tempting to use Go types instead of `attr.Value`
118-
implementations when the provider doesn't care about the distinction between an
119-
empty value, unknown, and null. But if Terraform has a null or unknown value
120-
and the provider asks the framework to store it in a type that can't hold it,
121-
`Get` will return an error. Make sure the types you are using can hold the
122-
values they might contain!
123-
124-
### String
125-
126-
Strings can be automatically converted to Go's `string` type (or any aliases of
127-
it, like `type MyString string`) as long as the string value is not null or
128-
unknown.
129-
130-
### Number
131-
132-
Numbers can be automatically converted to the following numeric types (or any
133-
aliases of them, like `type MyNumber int`) as long as the number value is not
134-
null or unknown:
135-
136-
* `int`, `int8`, `int16`, `int32`, `int64`
137-
* `uint`, `uint8`, `uint16`, `uint32`, `uint64`
138-
* `float32`, `float64`
139-
* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float)
140-
141-
An error will be returned if the value of the number cannot be stored in the numeric type supplied because of an overflow or other loss of precision.
142-
143-
### Boolean
144-
145-
Booleans can be automatically converted to Go's `bool` type (or any aliases of
146-
it, like `type MyBoolean bool`) as long as the boolean value is not null or
147-
unknown.
148-
149-
### List
150-
151-
Lists can be automatically converted to any Go slice type (or alias of a Go
152-
slice type, like `type MyList []string`), with the elements either being
153-
`attr.Value` implementations or being converted according to these rules. Go
154-
slice types are considered capable of handling null values; the slice will be
155-
set to nil. The `Get` method will still return an error for unknown list
156-
values.
157-
158-
### Map
159-
160-
Maps can be automatically converted to any Go map type with string keys (or any
161-
alias of a Go map type with string keys, like `type MyMap map[string]int`),
162-
with the elements either being `attr.Value` implementations or being converted
163-
according to these rules. Go map types are considered capable of handling null
164-
values; the map will be set to nil. The `Get` method will still return an error
165-
for unknown map values.
166-
167-
### Object
168-
169-
Objects can be automatically converted to any Go struct type with that follows these constraints:
170-
171-
* Every property on the struct must have a `tfsdk` struct tag.
172-
* The `tfsdk` struct tag must name an attribute in the object that it is being
173-
mapped to or be set to `-` to explicitly declare it does not map to an
174-
attribute in the object.
175-
* Every attribute in the object must have a corresponding struct tag.
176-
177-
These rules help prevent typos and human error from unwittingly discarding
178-
information by failing as early, consistently, and loudly as possible.
179-
180-
Properties can either be `attr.Value` implementations or will be converted
181-
according to these rules.
182-
183-
Unknown and null objects cannot be represented as structs and will return an
184-
error. Their attributes may contain unknown or null values if the attribute's
185-
type can hold them.
186-
187-
### Pointers
188-
189-
Pointers behave exactly like the type they are referencing, except they can hold
190-
null values. A pointer will be set to `nil` when representing a null value;
191-
otherwise, the conversion rules for that type will apply.
192-
193-
### Detected Interfaces
194-
195-
`Get` detects and utilizes the following interfaces, if the target implements
196-
them.
197-
198-
#### ValueConverter
199-
200-
If a value is being set on a Go type that implements the [`tftypes.ValueConverter`
201-
interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#ValueConverter),
202-
that interface will be delegated to to handle the conversion.
203-
204-
#### Unknownable
205-
206-
If the value is being set on a Go type that fills the `Unknownable` interface:
207-
208-
```go
209-
type Unknownable interface {
210-
SetUnknown(context.Context, bool) error
211-
SetValue(context.Context, interface{}) error
212-
GetUnknown(context.Context) bool
213-
GetValue(context.Context) interface{}
214-
}
215-
```
216-
217-
It will be considered capable of handling unknown values, and those methods
218-
will be used to populate it and retrieve its value. The `interface{}` being
219-
passed and retrieved will be of a type that can be passed to
220-
[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue).
221-
222-
#### Nullable
223-
224-
If the value is being set on a Go type that fills the `Nullable` interface:
225-
226-
```go
227-
type Nullable interface {
228-
SetNull(context.Context, bool) error
229-
SetValue(context.Context, interface{}) error
230-
GetNull(context.Context) bool
231-
GetValue(context.Context) interface{}
232-
}
233-
```
234-
235-
It will be considered capable of handling null values, and those methods will
236-
be used to populate it and retrieve its value. The `interface{}` being passed
237-
and retrieved will be of a type that can be passed to
238-
[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue).
115+
Refer to the [conversion rules](/plugin/framework/handling-data/conversion-rules)
116+
for more information about supported Go types.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
---
2+
page_title: 'Plugin Development - Framework: Conversion Rules'
3+
description: |-
4+
Converting from Framework Types to Go types and from Go types
5+
to Framework types.
6+
---
7+
8+
# Conversion Rules
9+
10+
## Converting from Framework Types to Go Types
11+
12+
!> **Warning:** It can be tempting to use Go types instead of `attr.Value`
13+
implementations when the provider doesn't care about the distinction between an
14+
empty value, unknown, and null. But if Terraform has a null or unknown value
15+
and the provider asks the framework to store it in a type that can't hold it,
16+
[`Get`](plugin/framework/handling-data/accessing-values#get-the-entire-configuration-plan-or-state)
17+
will return an error. Make sure the types you are using can hold the
18+
values they might contain!
19+
20+
### String
21+
22+
Strings can be automatically converted to Go's `string` type (or any aliases of
23+
it, like `type MyString string`) as long as the string value is not null or
24+
unknown.
25+
26+
### Number
27+
28+
Numbers can be automatically converted to the following numeric types (or any
29+
aliases of them, like `type MyNumber int`) as long as the number value is not
30+
null or unknown:
31+
32+
* `int`, `int8`, `int16`, `int32`, `int64`
33+
* `uint`, `uint8`, `uint16`, `uint32`, `uint64`
34+
* `float32`, `float64`
35+
* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float)
36+
37+
An error will be returned if the value of the number cannot be stored in the numeric type supplied because of an overflow or other loss of precision.
38+
39+
### Boolean
40+
41+
Booleans can be automatically converted to Go's `bool` type (or any aliases of
42+
it, like `type MyBoolean bool`) as long as the boolean value is not null or
43+
unknown.
44+
45+
### List
46+
47+
Lists can be automatically converted to any Go slice type (or alias of a Go
48+
slice type, like `type MyList []string`), with the elements either being
49+
`attr.Value` implementations or being converted according to these rules. Go
50+
slice types are considered capable of handling null values; the slice will be
51+
set to nil. The `Get` method will still return an error for unknown list
52+
values.
53+
54+
### Map
55+
56+
Maps can be automatically converted to any Go map type with string keys (or any
57+
alias of a Go map type with string keys, like `type MyMap map[string]int`),
58+
with the elements either being `attr.Value` implementations or being converted
59+
according to these rules. Go map types are considered capable of handling null
60+
values; the map will be set to nil. The `Get` method will still return an error
61+
for unknown map values.
62+
63+
### Object
64+
65+
Objects can be automatically converted to any Go struct type with that follows these constraints:
66+
67+
* Every property on the struct must have a `tfsdk` struct tag.
68+
* The `tfsdk` struct tag must name an attribute in the object that it is being
69+
mapped to or be set to `-` to explicitly declare it does not map to an
70+
attribute in the object.
71+
* Every attribute in the object must have a corresponding struct tag.
72+
73+
These rules help prevent typos and human error from unwittingly discarding
74+
information by failing as early, consistently, and loudly as possible.
75+
76+
Properties can either be `attr.Value` implementations or will be converted
77+
according to these rules.
78+
79+
Unknown and null objects cannot be represented as structs and will return an
80+
error. Their attributes may contain unknown or null values if the attribute's
81+
type can hold them.
82+
83+
### Pointers
84+
85+
Pointers behave exactly like the type they are referencing, except they can hold
86+
null values. A pointer will be set to `nil` when representing a null value;
87+
otherwise, the conversion rules for that type will apply.
88+
89+
### Detected Interfaces
90+
91+
[`Get`](/plugin/framework/handling-data/accessing-values#get-the-entire-configuration-plan-or-state)
92+
detects and utilizes the following interfaces, if the target implements
93+
them.
94+
95+
#### ValueConverter
96+
97+
If a value is being set on a Go type that implements the [`tftypes.ValueConverter`
98+
interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#ValueConverter),
99+
that interface will be delegated to to handle the conversion.
100+
101+
#### Unknownable
102+
103+
If the value is being set on a Go type that fills the `Unknownable` interface:
104+
105+
```go
106+
type Unknownable interface {
107+
SetUnknown(context.Context, bool) error
108+
SetValue(context.Context, interface{}) error
109+
GetUnknown(context.Context) bool
110+
GetValue(context.Context) interface{}
111+
}
112+
```
113+
114+
It will be considered capable of handling unknown values, and those methods
115+
will be used to populate it and retrieve its value. The `interface{}` being
116+
passed and retrieved will be of a type that can be passed to
117+
[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue).
118+
119+
#### Nullable
120+
121+
If the value is being set on a Go type that fills the `Nullable` interface:
122+
123+
```go
124+
type Nullable interface {
125+
SetNull(context.Context, bool) error
126+
SetValue(context.Context, interface{}) error
127+
GetNull(context.Context) bool
128+
GetValue(context.Context) interface{}
129+
}
130+
```
131+
132+
It will be considered capable of handling null values, and those methods will
133+
be used to populate it and retrieve its value. The `interface{}` being passed
134+
and retrieved will be of a type that can be passed to
135+
[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue).
136+
137+
## Converting from Go Types to Framework Types
138+
139+
The following is a list of schema types and the Go types they know how to
140+
accept in [`Set`](/plugin/framework/handling-data/writing-state#replace-the-entire-state)
141+
and [`SetAttribute`](/plugin/framework/handling-data/writing-state#set-a-single-attribute-or-block-value).
142+
143+
### String
144+
145+
Strings can be automatically created from Go's `string` type (or any aliases of
146+
it, like `type MyString string`).
147+
148+
### Number
149+
150+
Numbers can be automatically created from the following numeric types (or any
151+
aliases of them, like `type MyNumber int`):
152+
153+
* `int`, `int8`, `int16`, `int32`, `int64`
154+
* `uint`, `uint8`, `uint16`, `uint32`, `uint64`
155+
* `float32`, `float64`
156+
* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float)
157+
158+
### Boolean
159+
160+
Booleans can be automatically created from Go's `bool` type (or any aliases of
161+
it, like `type MyBoolean bool`).
162+
163+
### List
164+
165+
Lists can be automatically created from any Go slice type (or alias of a Go
166+
slice type, like `type MyList []string`), with the elements either being
167+
`attr.Value` implementations or being converted according to these rules.
168+
169+
### Map
170+
171+
Maps can be automatically created from any Go map type with string keys (or any
172+
alias of a Go map type with string keys, like `type MyMap map[string]int`),
173+
with the elements either being `attr.Value` implementations or being converted
174+
according to these rules.
175+
176+
### Object
177+
178+
Objects can be automatically created from any Go struct type with that follows
179+
these constraints:
180+
181+
* Every property on the struct must have a `tfsdk` struct tag.
182+
* The `tfsdk` struct tag must name an attribute in the object that it is being
183+
mapped to or be set to `-` to explicitly declare it does not map to an
184+
attribute in the object.
185+
* Every attribute in the object must have a corresponding struct tag.
186+
187+
These rules help prevent typos and human error from unwittingly discarding
188+
information by failing as early, consistently, and loudly as possible.
189+
190+
Properties can either be `attr.Value` implementations or will be converted
191+
according to these rules.
192+
193+
### Pointers
194+
195+
A nil pointer will be treated as a null value. Otherwise, the rules for the
196+
type the pointer is referencing apply.
197+
198+
### Detected Interfaces
199+
200+
`Set` detects and utilizes the following interfaces, if the target implements
201+
them.
202+
203+
#### ValueCreator
204+
205+
If a value is set on a Go type that implements the [`tftypes.ValueCreator`
206+
interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#ValueCreator),
207+
that interface will be delegated to to handle the conversion.
208+
209+
#### Unknownable
210+
211+
If a value is set on a Go type that fills the `Unknownable` interface:
212+
213+
```go
214+
type Unknownable interface {
215+
SetUnknown(context.Context, bool) error
216+
SetValue(context.Context, interface{}) error
217+
GetUnknown(context.Context) bool
218+
GetValue(context.Context) interface{}
219+
}
220+
```
221+
222+
It will be used to convert the value. The `interface{}` being passed and
223+
retrieved will be of a type that can be passed to
224+
[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue).
225+
226+
#### Nullable
227+
228+
If a value is set on a Go type that fills the `Nullable` interface:
229+
230+
```go
231+
type Nullable interface {
232+
SetNull(context.Context, bool) error
233+
SetValue(context.Context, interface{}) error
234+
GetNull(context.Context) bool
235+
GetValue(context.Context) interface{}
236+
}
237+
```
238+
239+
It will be used to convert the value. The `interface{}` being passed and
240+
retrieved will be of a type that can be passed to
241+
[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue).

0 commit comments

Comments
 (0)