diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 57ee08556..7b7fca50b 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -133,7 +133,7 @@ Code contributions that introduce new log messages should utilize the helper fun - [`FrameworkError`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/internal/logging#FrameworkError) - Logs at `ERROR` level, can be used to provide additional detail alongside user-facing errors that are returned with [`diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/diag#Diagnostics). - [`FrameworkWarn`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/internal/logging#FrameworkWarn) - Logs at `WARN` level, can be used to signal unexpected scenarios that may not result in a user-facing error, but can be used to track down potential provider implementation bugs. -- [`FrameworkDebug`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/internal/logging#FrameworkDebug) - Logs at `DEBUG` level, can be used to describe internal logic behavior, such as [semantic equality](https://developer.hashicorp.com/terraform/plugin/framework/handling-data/custom-types#semantic-equality) being triggered to preserve a prior value, or a null `Computed` attribute being marked as unknown. +- [`FrameworkDebug`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/internal/logging#FrameworkDebug) - Logs at `DEBUG` level, can be used to describe internal logic behavior, such as [semantic equality](https://developer.hashicorp.com/terraform/plugin/framework/handling-data/types/custom#semantic-equality) being triggered to preserve a prior value, or a null `Computed` attribute being marked as unknown. - [`FrameworkTrace`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/internal/logging#FrameworkTrace) - Logs at `TRACE` level, can be used to describe internal logic execution, such as logging a message before and after a provider-defined method is called. As the name suggests, these messages are used to "trace" where a program is at during execution. More general guidance about logging can be found in the [Plugin Development documentation.](https://developer.hashicorp.com/terraform/plugin/log/managing) diff --git a/website/data/plugin-framework-nav-data.json b/website/data/plugin-framework-nav-data.json index 77182e5df..8003f0c0c 100644 --- a/website/data/plugin-framework-nav-data.json +++ b/website/data/plugin-framework-nav-data.json @@ -131,11 +131,134 @@ }, { "title": "Attributes", - "path": "handling-data/attributes" + "routes": [ + { + "title": "Overview", + "path": "handling-data/attributes" + }, + { + "title": "Bool", + "path": "handling-data/attributes/bool" + }, + { + "title": "Float64", + "path": "handling-data/attributes/float64" + }, + { + "title": "Int64", + "path": "handling-data/attributes/int64" + }, + { + "title": "List", + "path": "handling-data/attributes/list" + }, + { + "title": "List Nested", + "path": "handling-data/attributes/list-nested" + }, + { + "title": "Map", + "path": "handling-data/attributes/map" + }, + { + "title": "Map Nested", + "path": "handling-data/attributes/map-nested" + }, + { + "title": "Number", + "path": "handling-data/attributes/number" + }, + { + "title": "Object", + "path": "handling-data/attributes/object" + }, + { + "title": "Set", + "path": "handling-data/attributes/set" + }, + { + "title": "Set Nested", + "path": "handling-data/attributes/set-nested" + }, + { + "title": "Single Nested", + "path": "handling-data/attributes/single-nested" + }, + { + "title": "String", + "path": "handling-data/attributes/string" + } + ] }, { "title": "Blocks", - "path": "handling-data/blocks" + "routes": [ + { + "title": "Overview", + "path": "handling-data/blocks" + }, + { + "title": "List Nested", + "path": "handling-data/blocks/list-nested" + }, + { + "title": "Set Nested", + "path": "handling-data/blocks/set-nested" + }, + { + "title": "Single Nested", + "path": "handling-data/blocks/single-nested" + } + ] + }, + { + "title": "Types", + "routes": [ + { + "title": "Overview", + "path": "handling-data/types" + }, + { + "title": "Bool", + "path": "handling-data/types/bool" + }, + { + "title": "Float64", + "path": "handling-data/types/float64" + }, + { + "title": "Int64", + "path": "handling-data/types/int64" + }, + { + "title": "List", + "path": "handling-data/types/list" + }, + { + "title": "Map", + "path": "handling-data/types/map" + }, + { + "title": "Number", + "path": "handling-data/types/number" + }, + { + "title": "Object", + "path": "handling-data/types/object" + }, + { + "title": "Set", + "path": "handling-data/types/set" + }, + { + "title": "String", + "path": "handling-data/types/string" + }, + { + "title": "Custom Types", + "path": "handling-data/types/custom" + } + ] }, { "title": "Paths", @@ -152,14 +275,6 @@ { "title": "Writing Data", "path": "handling-data/writing-state" - }, - { - "title": "Conversion Rules", - "path": "handling-data/conversion-rules" - }, - { - "title": "Custom Types", - "path": "handling-data/custom-types" } ] }, diff --git a/website/docs/plugin/framework/handling-data/accessing-values.mdx b/website/docs/plugin/framework/handling-data/accessing-values.mdx index e672da3b5..a2624da4d 100644 --- a/website/docs/plugin/framework/handling-data/accessing-values.mdx +++ b/website/docs/plugin/framework/handling-data/accessing-values.mdx @@ -60,7 +60,7 @@ func (r ThingResource) Create(ctx context.Context, ``` The configuration, plan, and state data is represented as an object, and -accessed like an object. Refer to the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#converting-from-framework-types-to-go-types) for an +accessed like an object. Refer to the [object type](/terraform/plugin/framework/handling-data/types/object) documentation for an explanation on how objects can be converted into Go types. To descend into deeper nested data structures, the `types.List`, `types.Map`, and `types.Set` types each have an `ElementsAs()` method. The `types.Object` type has an `As()` method. @@ -109,6 +109,3 @@ or null. It is safe to assume: In any other circumstances, the provider is responsible for handling the possibility that an unknown or null value may be presented to it. - -Refer to the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#converting-from-framework-types-to-go-types) -for more information about supported Go types. diff --git a/website/docs/plugin/framework/handling-data/attributes.mdx b/website/docs/plugin/framework/handling-data/attributes.mdx deleted file mode 100644 index a6b158e5d..000000000 --- a/website/docs/plugin/framework/handling-data/attributes.mdx +++ /dev/null @@ -1,582 +0,0 @@ ---- -page_title: 'Plugin Development - Framework: Attribute Types' -description: >- - Learn the attributes in the provider development framework and how to make - your own. Attributes are fields in a resource, data source, or provider. ---- - -# 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: - -```tf -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. - -## Framework Attribute Types - -The framework provides a standard set of schema attribute types that are based on the framework type system available in the [`types` package](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types). These types bridge the implementation details between Terraform's type system and Go code in providers. The framework attribute types also support provider-defined types via a `CustomType` field. Refer to [Custom Types](/terraform/plugin/framework/handling-data/custom-types) for more information about implementing provider-defined types. - -| Terraform Type | Framework Attribute Type | Framework Value Type | Known Value Go Type | Use Case | -|----------------|--------------------------|----------------------|---------------------|----------| -| `bool` | `schema.BoolAttribute` | `types.Bool` | `bool` | Boolean true or false | -| `number` | `schema.Float64Attribute` | `types.Float64` | `float64` | 64-bit floating point number | -| `number` | `schema.Int64Attribute` | `types.Int64` | `int64` | 64-bit integer | -| `list` | `schema.ListAttribute` | `types.List` | `[]attr.Value` | Ordered collection of single element type | -| `map` | `schema.MapAttribute` | `types.Map` | `map[string]attr.Value` | Mapping of arbitrary string keys to single element type | -| `number` | `schema.NumberAttribute` | `types.Number` | `*big.Float` | Large floating point or number | -| `object` | `schema.ObjectAttribute` | `types.Object` | `map[string]attr.Value` | Structure mapping explicit string attibute keys to any value type | -| `set` | `schema.SetAttribute` | `types.Set` | `[]attr.Value` | Unordered, unique collection of single element type | -| `string` | `schema.StringAttribute` | `types.String` | `string` | Collection of UTF-8 encoded characters | - -### String - -Strings are a UTF-8 encoded collection of bytes. - -Given an example Terraform configuration that sets a string value to the `example_attribute` attribute: - -```tf -example_attribute = "terraform" -``` - -The associated schema type is `schema.StringAttribute`: - -```go -"example_attribute": schema.StringAttribute{ - // ... other fields ... -} -``` - -The associated framework type is [`types.StringType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringType) and value type is [`types.String`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#String) in configuration, plan, and state data. - -Access `types.String` information via the following methods: - -* [`(types.String).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#String.IsNull): Returns true if the string is null. -* [`(types.String).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#String.IsUnknown): Returns true if the string is unknown. -* [`(types.String).ValueString() string`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#String.ValueString): Returns the known string, or an empty string if null or unknown. - -The `(types.String).String()` method is reserved for debugging purposes and returns `""` if the value is null and `""` if the value is unknown. Use `(types.String).ValueString()` for any Terraform data handling. - -Call one of the following to create a `types.String`: - -* [`types.StringNull()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringNull): A null string value. -* [`types.StringUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringUnknown): An unknown string value. -* [`types.StringValue(string)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringValue): A known value. - -### Int64 - -Int64 are 64-bit integer values, such as `1234`. For 64-bit floating point numbers, use [`Float64`](#float64). For generic number handling, use [`Number`](#number). - -Given an example Terraform configuration that sets an integer value to the `example_attribute` attribute: - -```tf -example_attribute = 1234 -``` - -The associated schema type is `schema.Int64Attribute`: - -```go -"example_attribute": schema.Int64Attribute{ - // ... other fields ... -} -``` - -The associated framework type is [`types.Int64Type`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Type) and value type is [`types.Int64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64) in configuration, plan, and state data. - -Access `types.Int64` information via the following methods: - -* [`(types.Int64).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64.IsNull): Returns true if the integer is null. -* [`(types.Int64).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64.IsUnknown): Returns true if the integer is unknown. -* [`(types.Int64).ValueInt64() int64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64.ValueInt64): Returns the known `int64` value, or `0` if null or unknown. - -Call one of the following to create a `types.Int64`: - -* [`types.Int64Null()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Null): A null integer value. -* [`types.Int64Unknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Unknown): An unknown integer value. -* [`types.Int64Value(int64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Value): A known value. - -### Float64 - -Float64 are 64-bit floating point values, such as `1234.5`. For 64-bit integer numbers, use [`Int64`](#int64). For generic number handling, use [`Number`](#number). - -Given an example Terraform configuration that sets a floating point value to the `example_attribute` attribute: - -```tf -example_attribute = 1234.5 -``` - -The associated schema type is `schema.Float64Attribute`: - -```go -"example_attribute": schema.Float64Attribute{ - // ... other fields ... -} -``` - -The associated framework type is [`types.Float64Type`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Type) and value type is [`types.Float64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64) in configuration, plan, and state data. - -Access `types.Float64` information via the following methods: - -* [`(types.Float64).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64.IsNull): Returns true if the number is null. -* [`(types.Float64).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64.IsUnknown): Returns true if the number is unknown. -* [`(types.Float64).ValueFloat64() float64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64.ValueFloat64): Returns the known `float64` value, or `0.0` if null or unknown. - -Call one of the following to create a `types.Float64`: - -* [`types.Float64Null()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Null): A null number value. -* [`types.Float64Unknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Unknown): An unknown number value. -* [`types.Float64Value(float64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Value): A known value. - -### Number - -Numbers are numeric values, both whole values like `12` or fractional values like `3.14`. Use this type for exceptionally large numbers. For 64-bit integer numbers, use [`Int64`](#int64). For 64-bit floating point numbers, use [`Float64`](#float64). - -Given an example Terraform configuration that sets a number value to the `example_attribute` attribute: - -```tf -example_attribute = 123 -``` - -The associated schema type is `schema.NumberAttribute`: - -```go -"example_attribute": schema.NumberAttribute{ - // ... other fields ... -} -``` - -The associated framework type is [`types.NumberType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberType) and value type is [`types.Number`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Number) in configuration, plan, and state data. - -Access `types.Number` information via the following methods: - -* [`(types.Number).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Number.IsNull): Returns true if the number is null. -* [`(types.Number).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Number.IsUnknown): Returns true if the number is unknown. -* [`(types.Number).ValueBigFloat() *big.Float`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Number.ValueBigFloat): Returns the known `*big.Float` value, or `nil` if null or unknown. - -Call one of the following to create a `types.Number`: - -* [`types.NumberNull()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberNull): A null number value. -* [`types.NumberUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberUnknown): An unknown number value. -* [`types.NumberValue(*big.Float)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberValue): A known value. - -### Bool - -Bools are boolean values that can either be true or false. - -Given an example Terraform configuration that sets a boolean value to the `example_attribute` attribute: - -```tf -example_attribute = true -``` - -The associated schema type is `schema.BoolAttribute`: - -```go -"example_attribute": schema.BoolAttribute{ - // ... other fields ... -} -``` - -The associated framework type is [`types.BoolType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolType) and value type is [`types.Bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Bool) in configuration, plan, and state data. - -Access `types.Bool` information via the following methods: - -* [`(types.Bool).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Bool.IsNull): Returns true if the boolean is null. -* [`(types.Bool).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Bool.IsUnknown): Returns true if the boolean is unknown. -* [`(types.Bool).ValueBool() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Bool.ValueBool): Returns the known `bool` value, or `false` if null or unknown. - -Call one of the following to create a `types.Bool`: - -* [`types.BoolNull()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolNull): A null boolean value. -* [`types.BoolUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolUnknown): An unknown boolean value. -* [`types.BoolValue(bool)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolValue): A known value. - -### List - -Lists are ordered collections of a single element type. - --> Use [List Nested Attributes](/terraform/plugin/framework/handling-data/attributes#listnestedattribute) for lists of objects that need additional schema information. Use [Set](#set) for unordered collections. - -Given an example Terraform configuration that sets a list of string values to the `example_attribute` attribute: - -```tf -example_attribute = ["red", "blue", "green"] -``` - -The associated schema type is `schema.ListAttribute`: - -```go -"example_attribute": schema.ListAttribute{ - ElementType: types.StringType, - // ... other fields ... -} -``` - -The associated framework type is [`types.ListType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListType) and value type is [`types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#List) in configuration, plan, and state data. - -Access `types.List` information via the following methods: - -* [`(types.List).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#List.IsNull): Returns true if the list is null. -* [`(types.List).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#List.IsUnknown): Returns true if the list is unknown. Returns false if the number of elements is known, any of which may be unknown. -* [`(types.List).Elements() []attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#List.Elements): Returns the known `[]attr.Value` value, or `nil` if null or unknown. -* [`(types.List).ElementsAs(context.Context, any, bool) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#List.ElementsAs): Converts the known values into the given Go type, if possible, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#list). - -Call one of the following to create a `types.List`: - -* [`types.ListNull(attr.Type) types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListNull): A null list value with the given element type. -* [`types.ListUnknown(attr.Type) types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListUnknown): An unknown list value with the given element type. -* [`types.ListValue(attr.Type, []attr.Value) (types.List, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValue): A known value with the given element type and values. -* [`types.ListValueFrom(context.Context, attr.Type, any) (types.List, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom): A known value with the given element type and values. Can convert from standard Go types, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#list-1). -* [`types.ListValueMust(map[string]attr.Type, map[string]attr.Value) types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueMust): A known value with the given element type and values. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. - -### Map - -Maps are mappings of arbitrary string keys to values of a single element type. - --> Use [Map Nested Attributes](/terraform/plugin/framework/handling-data/attributes#mapnestedattribute) for maps of objects that need additional schema information. Use [Object](#object) for structures of explicit string attribute names to any value. - -Given an example Terraform configuration that sets a map of string values to the `example_attribute` attribute: - -```tf -example_attribute = { - red = "fire", - blue = "sky", - green = "plant", -} -``` - -The associated schema type is `schema.MapAttribute`: - -```go -"example_attribute": schema.MapAttribute{ - ElementType: types.StringType, - // ... other fields ... -} -``` - -The associated framework type is [`types.MapType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapType) and value type is [`types.Map`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Map) in configuration, plan, and state data. - -Access `types.Map` information via the following methods: - -* [`(types.Map).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Map.IsNull): Returns true if the map is null. -* [`(types.Map).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Map.IsUnknown): Returns true if the map is unknown. Returns false if the number of elements is known, any of which may be unknown. -* [`(types.Map).Elements() map[string]attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Map.Elements): Returns the known `map[string]attr.Value` value, or `nil` if null or unknown. -* [`(types.Map).ElementsAs(context.Context, any, bool) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Map.ElementsAs): Converts the known values into the given Go type, if possible, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#map). - -Call one of the following to create a `types.Map`: - -* [`types.MapNull(attr.Type)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapNull): A null map value with the given element type. -* [`types.MapUnknown(attr.Type)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapUnknown): An unknown map value with the given element type. -* [`types.MapValue(attr.Type, map[string]attr.Value) (types.Map, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValue): A known value with the given element type and values. -* [`types.MapValueFrom(context.Context, attr.Type, any) (types.Map, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom): A known value with the given element type and values. Can convert from standard Go types, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#map-1). -* [`types.MapValueMust(map[string]attr.Type, map[string]attr.Value) types.Map`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueMust): A known value with the given element type and values. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. - -### Object - -Objects are mappings of explicit string attribute names to values of any type. Objects must always declare all attribute values, even when those attributes are null or unknown, unless the entire object is null or unknown. - --> Use [Single Nested Attributes](/terraform/plugin/framework/handling-data/attributes#singlenestedattribute) for objects that need additional schema information. Use [Map](#map) for mappings of arbitrary string keys to a single element type. - -Given an example Terraform configuration that sets a map of string values to the `example_attribute` attribute: - -```tf -example_attribute = { - pi = 3.14 - demo = true - color = "red" -} -``` - -The associated schema type is `schema.ObjectAttribute`: - -```go -"example_attribute": schema.ObjectAttribute{ - AttributeTypes: map[string]attr.Type{ - "pi": types.Float64Type, - "demo": types.BoolType, - "color": types.StringType, - }, - // ... other fields ... -} -``` - -The associated framework type is [`types.ObjectType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectType) and value type is [`types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Object) in configuration, plan, and state data. - -Access `types.Object` information via the following methods: - -* [`(types.Object).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Object.IsNull): Returns true if the object is null. -* [`(types.Object).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Object.IsUnknown): Returns true if the object is unknown. Returns false if the number of elements is known, any of which may be unknown. -* [`(types.Object).Attributes() map[string]attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Object.Attributes): Returns the known `map[string]attr.Value` value, or `nil` if null or unknown. -* [`(types.Object).As(context.Context, any, ObjectAsOptions) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Object.As): Converts the known values into the given Go type, if possible, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#object). - -Call one of the following to create a `types.Object`: - -* [`types.ObjectNull(map[string]attr.Type) types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectNull): A null object value with the given attribute type mapping. -* [`types.ObjectUnknown(map[string]attr.Type) types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectUnknown): An unknown object value with the given attribute type mapping. -* [`types.ObjectValue(map[string]attr.Type, map[string]attr.Value) (types.Object, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValue): A known value with the given attribute type mapping and attribute value mapping. -* [`types.ObjectValueFrom(context.Context, attr.Type, any) (types.Object, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom): A known value with the given attribute type mapping and values. Can convert from standard Go types, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#object-1). -* [`types.ObjectValueMust(map[string]attr.Type, map[string]attr.Value) types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueMust): A known value with the given attribute type mapping and attribute value mapping. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. - -### Set - -Set are unordered, unique collections of a single element type. - --> Use [Set Nested Attributes](/terraform/plugin/framework/handling-data/attributes#setnestedattribute) for sets of objects that need additional schema information. Use [List](#list) for ordered collections. - -Given an example Terraform configuration that sets a set of string values to the `example_attribute` attribute: - -```tf -example_attribute = ["red", "blue", "green"] -``` - -The associated schema type is `schema.SetAttribute`: - -```go -"example_attribute": schema.SetAttribute{ - ElementType: types.StringType, - // ... other fields ... -} -``` - -The associated framework type is [`types.SetType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetType) and value type is [`types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Set) in configuration, plan, and state data. - -Access `types.Set` information via the following methods: - -* [`(types.Set).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Set.IsNull): Returns true if the list is null. -* [`(types.Set).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Set.IsUnknown): Returns true if the list is unknown. Returns false if the number of elements is known, any of which may be unknown. -* [`(types.Set).Elements() []attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Set.Elements): Returns the known `[]attr.Value` value, or `nil` if null or unknown. -* [`(types.Set).ElementsAs(context.Context, any, bool) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Set.ElementsAs): Converts the known values into the given Go type, if possible, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules). - -Call one of the following to create a `types.Set`: - -* [`types.SetNull(attr.Type) types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetNull): A null list value with the given element type. -* [`types.SetUnknown(attr.Type) types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetUnknown): An unknown list value with the given element type. -* [`types.SetValue(attr.Type, []attr.Value) (types.Set, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValue): A known value with the given element type and values. -* [`types.SetValueFrom(context.Context, attr.Type, any) (types.Set, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom): A known value with the given element type and values. Can convert from standard Go types, using the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules). -* [`types.SetValueMust(map[string]attr.Type, map[string]attr.Value) types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueMust): A known value with the given element type and values. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. - -### Nested Attributes - --> Only supported when using protocol version 6. - -[Nested attributes](/terraform/plugin/framework/handling-data/attributes#nested-attributes) enable provider developers to define objects of attributes which fully support attribute behaviors and practitioners to configure these directly using [expressions](/terraform/language/expressions). - -#### SingleNestedAttribute - -With single nested attributes, the attribute behaves like an object. The practitioner can only specify one definition of the nested attributes. - -```tf -resource "example_foo" "bar" { - nested_attribute = { - hello = "world" - demo = true - } -} -``` - -```go -func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - Attributes: map[string]schema.Attribute{ - "nested_attribute": schema.SingleNestedAttribute{ - /* ... */ - Attributes: map[string]schema.Attribute{ - "hello": schema.StringAttribute{ - /* ... */ - }, - "demo": schema.BoolAttribute{ - /* ... */ - }, - }, - }, - }, - } -} -``` - -#### ListNestedAttribute - -With list nested attributes, the attribute behaves like a list of objects. The practitioner can -specify any number of groups of these attributes. - -```tf -resource "example_foo" "bar" { - nested_attribute = [ - { - hello = "world" - demo = true - }, - { - hello = "moon" - demo = false - }, - ] -} -``` - -```go -func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - Attributes: map[string]schema.Attribute{ - "nested_attribute": schema.ListNestedAttribute{ - /* ... */ - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "hello": schema.StringAttribute{ - /* ... */ - }, - "demo": schema.BoolAttribute{ - /* ... */ - }, - }, - }, - }, - }, - } -} -``` - -#### MapNestedAttribute - -With map nested attributes, the attribute behaves like a map of objects. The practitioner can -specify any number of groups of these attributes, with string keys associated -with each group. - -```tf -resource "example_foo" "bar" { - nested_attribute = { - "red" = { - hello = "world" - demo = true - }, - "blue" = { - hello = "moon" - demo = false - }, - } -} -``` - -```go -func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - Attributes: map[string]schema.Attribute{ - "nested_attribute": schema.MapNestedAttribute{ - /* ... */ - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "hello": schema.StringAttribute{ - /* ... */ - }, - "demo": schema.BoolAttribute{ - /* ... */ - }, - }, - }, - }, - }, - } -} -``` - -#### SetNestedAttribute - -With set nested attributes, the attributes behave like a set of objects. The practitioner can -specify any number of groups of these attributes. - -```tf -resource "example_foo" "bar" { - nested_attribute = [ - { - hello = "world" - demo = true - }, - { - hello = "moon" - demo = false - }, - ] -} -``` - -```go -func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - Attributes: map[string]schema.Attribute{ - "nested_attribute": schema.SetNestedAttribute{ - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "hello": schema.StringAttribute{ - /* ... */ - }, - "demo": schema.BoolAttribute{ - /* ... */ - }, - }, - }, - }, - }, - } -} -``` - -## 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. - -Refer to [Custom Types](/terraform/plugin/framework/handling-data/custom-types) for further details on creating provider-defined types and values. - -## Common Custom Types and Values - -A collection of Go modules have been created with attribute value and type implementations for common use cases, such as normalized JSON strings, IPv4/IPv6 addresses, and RFC3339 time strings. Refer to [Common Custom Types](/terraform/plugin/framework/handling-data/custom-types#common-custom-types) for further details. \ No newline at end of file diff --git a/website/docs/plugin/framework/handling-data/attributes/bool.mdx b/website/docs/plugin/framework/handling-data/attributes/bool.mdx new file mode 100644 index 000000000..e2278df5d --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/bool.mdx @@ -0,0 +1,120 @@ +--- +page_title: 'Plugin Development - Framework: Bool Attribute' +description: >- + Learn the bool attribute type in the provider development framework. +--- + +# Bool Attribute + +Bool attributes store a boolean true or false value. Values are represented by a [bool type](/terraform/plugin/framework/handling-data/types/bool) in the framework. + +In this Terraform configuration example, a bool attribute named `example_attribute` is set to the value `true`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = true +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a bool value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.BoolAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#BoolAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.BoolAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#BoolAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.BoolAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#BoolAttribute) | + +In this example, a resource schema defines a top level required bool attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.BoolAttribute{ + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the bool value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [bool type](/terraform/plugin/framework/handling-data/types/bool). Refer to the collection attribute type documentation for additional details. + +If the bool value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value according to the [bool type](/terraform/plugin/framework/handling-data/types/bool). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`booldefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault) package defines common use case `Default` implementations: + +- [`StaticBool(bool)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault#StaticBool): Define a static bool default value for the attribute. + +The [`boolplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`boolvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/boolvalidator) package within that module has bool attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [bool type](/terraform/plugin/framework/handling-data/types/bool#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [bool type](/terraform/plugin/framework/handling-data/types/bool#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/float64.mdx b/website/docs/plugin/framework/handling-data/attributes/float64.mdx new file mode 100644 index 000000000..938657856 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/float64.mdx @@ -0,0 +1,126 @@ +--- +page_title: 'Plugin Development - Framework: Float64 Attribute' +description: >- + Learn the float64 attribute type in the provider development framework. +--- + +# Float64 Attribute + + + +Use [Int64 Attribute](/terraform/plugin/framework/handling-data/attributes/int64) for 64-bit integer numbers. Use [Number Attribute](/terraform/plugin/framework/handling-data/attributes/number) for arbitrary precision numbers. + + + +Float64 attributes store a 64-bit floating point number. Values are represented by a [float64 type](/terraform/plugin/framework/handling-data/types/float64) in the framework. + +In this Terraform configuration example, a float64 attribute named `example_attribute` is set to the value `1.23`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = 1.23 +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a float64 value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.Float64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#Float64Attribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.Float64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#Float64Attribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.Float64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#Float64Attribute) | + +In this example, a resource schema defines a top level required float64 attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.Float64Attribute{ + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the string value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [float64 type](/terraform/plugin/framework/handling-data/types/float64). Refer to the collection attribute type documentation for additional details. + +If the string value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value according to the [float64 type](/terraform/plugin/framework/handling-data/types/float64). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`float64default`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/float64default) package defines common use case `Default` implementations: + +- [`StaticFloat64(float64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/float64default#StaticFloat64): Define a static float64 default value for the attribute. + +The [`float64planmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/float64planmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/float64planmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/float64planmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/float64planmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/float64planmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`float64validator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/float64validator) package within that module has float64 attribute validators such as minimum, maximum, and defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [float64 type](/terraform/plugin/framework/handling-data/types/float64#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [float64 type](/terraform/plugin/framework/handling-data/types/float64#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/index.mdx b/website/docs/plugin/framework/handling-data/attributes/index.mdx new file mode 100644 index 000000000..72273daa7 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/index.mdx @@ -0,0 +1,72 @@ +--- +page_title: 'Plugin Development - Framework: Attributes' +description: >- + Learn the attribute types in the provider development framework. Attributes + are fields in a resource, data source, or provider schema. +--- + +# Attributes + +Attributes are value storing fields in resource, data source, or provider [schemas](/terraform/plugin/framework/handling-data/schemas). Every attribute has an associated [value type](/terraform/plugin/framework/handling-data/types), which describes the kind of data the attribute can hold. Attributes also can describe value plan modifiers (resources only) and value validators in addition to those defined by the value type. + +## Available Attribute Types + +Schemas support the following attribute types: + +- [Primitive](#primitive-attribute-types): Attribute that contains a single value, such as a boolean, number, or string. +- [Collection](#collection-attribute-types): Attribute that contains multiple values of a single element type, such as a list, map, or set. +- [Nested](#nested-attribute-types): Attribute that defines a structure of explicit attibute names to attribute definitions, potentially with a wrapping collection type, such as a single structure of attributes or a list of structures of attributes. +- [Object](#object-attribute-type): Attribute that defines a structure of explicit attribute names to type-only definitions. + +### Primitive Attribute Types + +Attribute types that contain a single data value, such as a boolean, number, or string. + +| Attribute Type | Use Case | +|----------------|----------| +| [Bool](/terraform/plugin/framework/handling-data/attributes/bool) | Boolean true or false | +| [Float64](/terraform/plugin/framework/handling-data/attributes/float64) | 64-bit floating point number | +| [Int64](/terraform/plugin/framework/handling-data/attributes/int64) | 64-bit integer number | +| [Number](/terraform/plugin/framework/handling-data/attributes/number) | Arbitrary precision (generally over 64-bit, up to 512-bit) number | +| [String](/terraform/plugin/framework/handling-data/attributes/bool) | Collection of UTF-8 encoded characters | + +#### Collection Attribute Types + +Attribute types that contain multiple values of a single element type, such as a list, map, or set. + +| Attribute Type | Use Case | +|----------------|----------| +| [List](/terraform/plugin/framework/handling-data/attributes/list) | Ordered collection of single element type | +| [Map](/terraform/plugin/framework/handling-data/attributes/map) | Mapping of arbitrary string keys to values of single element type | +| [Set](/terraform/plugin/framework/handling-data/attributes/set) | Unordered, unique collection of single element type | + +#### Nested Attribute Types + + + +Only supported when using [protocol version 6](/terraform/plugin/framework/provider-servers). + + + +Attribute types that define a structure of explicit attibute names to attribute definitions, potentially with a wrapping collection type, such as a single structure of attributes or a list of structures of attributes. + +| Attribute Type | Use Case | +|----------------|----------| +| [List Nested](/terraform/plugin/framework/handling-data/attributes/list-nested) | Ordered collection of structures of attributes | +| [Map Nested](/terraform/plugin/framework/handling-data/attributes/map-nested) | Mapping of arbitrary string keys to structures of attributes | +| [Set Nested](/terraform/plugin/framework/handling-data/attributes/set-nested) | Unordered, unique collection of structures of attributes | +| [Single Nested](/terraform/plugin/framework/handling-data/attributes/single-nested) | Single structure of attributes | + +#### Object Attribute Type + + + +Use [nested attribute types](#nested-attribute-types) where possible. Objects have limited capabilities. + + + +Attribute type that defines a structure of explicit attribute names to type-only definitions. + +| Attribute Type | Use Case | +|----------------|----------| +| [Object](/terraform/plugin/framework/handling-data/attributes/object) | Single structure mapping explicit attribute names to type definitions | diff --git a/website/docs/plugin/framework/handling-data/attributes/int64.mdx b/website/docs/plugin/framework/handling-data/attributes/int64.mdx new file mode 100644 index 000000000..ed526b2ce --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/int64.mdx @@ -0,0 +1,126 @@ +--- +page_title: 'Plugin Development - Framework: Int64 Attribute' +description: >- + Learn the int64 attribute type in the provider development framework. +--- + +# Int64 Attribute + + + +Use [Float64 Attribute](/terraform/plugin/framework/handling-data/attributes/float64) for 64-bit floating point numbers. Use [Number Attribute](/terraform/plugin/framework/handling-data/attributes/number) for arbitrary precision numbers. + + + +Int64 attributes store a 64-bit integer number. Values are represented by a [int64 type](/terraform/plugin/framework/handling-data/types/int64) in the framework. + +In this Terraform configuration example, an int64 attribute named `example_attribute` is set to the value `123`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = 123 +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a int64 value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.Int64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#Int64Attribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.Int64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#Int64Attribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.Int64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#Int64Attribute) | + +In this example, a resource schema defines a top level required int64 attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.Int64Attribute{ + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the string value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [int64 type](/terraform/plugin/framework/handling-data/types/int64). Refer to the collection attribute type documentation for additional details. + +If the string value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value according to the [int64 type](/terraform/plugin/framework/handling-data/types/int64). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`int64default`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default) package defines common use case `Default` implementations: + +- [`StaticInt64(int64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default#StaticInt64): Define a static int64 default value for the attribute. + +The [`int64planmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`int64validator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/int64validator) package within that module has int64 attribute validators such as minimum, maximum, and defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [int64 type](/terraform/plugin/framework/handling-data/types/int64#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [int64 type](/terraform/plugin/framework/handling-data/types/int64#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/list-nested.mdx b/website/docs/plugin/framework/handling-data/attributes/list-nested.mdx new file mode 100644 index 000000000..df625545e --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/list-nested.mdx @@ -0,0 +1,175 @@ +--- +page_title: 'Plugin Development - Framework: List Nested Attribute' +description: >- + Learn the list nested attribute type in the provider development framework. +--- + +# List Nested Attribute + +List nested attributes store an ordered collection of nested objects. Values are represented by a [list type](/terraform/plugin/framework/handling-data/types/list) in the framework, containing elements of [object type](/terraform/plugin/framework/handling-data/types/object). + +In this Terraform configuration example, a list nested attribute named `example_attribute` is set to the ordered object values of `attr` to `"one"` and `attr` to `"two"`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = [ + { + attr = "one" + }, + { + attr = "two" + }, + ] +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a list nested value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ListNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ListNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ListNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ListNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ListNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ListNestedAttribute) | + +The `NestedObject` field must be defined, which represents the [object value type](/terraform/plugin/framework/handling-data/types/object) of every element of the list. + +In this example, a resource schema defines a top level required list nested attribute named `example_attribute` with a required string attribute named `attr`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.ListNestedAttribute{ + NestedObject: schema.NestedAttributeOjbect{ + Attributes: map[string]schema.Attribute{ + "attr": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.List` of `types.Object` where the `types.Object` is a mapping of `attr` to `types.String`. + +A nested attribute type may itself contain further collection or nested attribute types, if necessary. + +In this example, a resource schema defines a top level required list nested attribute named `example_attribute` with a required list of strings attribute named `attr1` and an optional single nested attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.ListNestedAttribute{ + NestedObject: schema.NestedAttributeOjbect{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ /* ... */ }, + Optional: true, + // ... potentially other fields ... + }, + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.List` of `types.Object` where the `types.Object` is a mapping of `attr1` to `types.List` of `types.String` and `attr2` to `types.Object`. + +### Configurability + + + +Only the list nested attribute itself is defined by the `schema.ListNestedAttribute` configurability fields. Nested attributes must define their own configurability fields within each attribute definition. + + + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`listdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.List)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault#StaticValue): Define a static list default value for the attribute. + +The [`listplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`listvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/listvalidator) package within that module has list attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [list type](/terraform/plugin/framework/handling-data/types/list#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [list type](/terraform/plugin/framework/handling-data/types/list#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/list.mdx b/website/docs/plugin/framework/handling-data/attributes/list.mdx new file mode 100644 index 000000000..214e4c242 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/list.mdx @@ -0,0 +1,144 @@ +--- +page_title: 'Plugin Development - Framework: List Attribute' +description: >- + Learn the list attribute type in the provider development framework. +--- + +# List Attribute + +List attributes store an ordered collection of single element type. Values are represented by a [list type](/terraform/plugin/framework/handling-data/types/list) in the framework, containing elements of the element type. + +In this Terraform configuration example, a list of string attribute named `example_attribute` is set to the ordered values `"one"` and `"two"`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = ["one", "two"] +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a list value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ListAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ListAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ListAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ListAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ListAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ListAttribute) | + +The `ElementType` field must be defined, which represents the single [value type](/terraform/plugin/framework/handling-data/types) of every element of the list. + +In this example, a resource schema defines a top level required list of strings attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +An element type may itself contain further collection types, if necessary. + +In this example, a resource schema defines a top level required list of list of strings attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.ListAttribute{ + ElementType: types.ListType{ + ElemType: types.StringType, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the list value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [list type](/terraform/plugin/framework/handling-data/types/list). Refer to the collection attribute type documentation for additional details. + +If the list value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value according to the [list type](/terraform/plugin/framework/handling-data/types/list). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`listdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.List)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault#StaticValue): Define a static list default value for the attribute. + +The [`listplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`listvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/listvalidator) package within that module has list attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [list type](/terraform/plugin/framework/handling-data/types/list#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [list type](/terraform/plugin/framework/handling-data/types/list#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/map-nested.mdx b/website/docs/plugin/framework/handling-data/attributes/map-nested.mdx new file mode 100644 index 000000000..6001d3fac --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/map-nested.mdx @@ -0,0 +1,175 @@ +--- +page_title: 'Plugin Development - Framework: Map Nested Attribute' +description: >- + Learn the map nested attribute type in the provider development framework. +--- + +# Map Nested Attribute + +Map nested attributes store mapping of arbitrary string keys to nested objects. Values are represented by a [map type](/terraform/plugin/framework/handling-data/types/map) in the framework, containing elements of [object type](/terraform/plugin/framework/handling-data/types/object). + +In this Terraform configuration example, a map nested attribute named `example_attribute` is set to the mapped values of `"key1"` to the object value of `attr` to `"one"` and `"key2"` to the object value of `attr` to `"two"`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = { + "key1" = { + attr = "one" + }, + "key2" = { + attr = "two" + }, + } +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a map nested value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.MapNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#MapNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.MapNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#MapNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.MapNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#MapNestedAttribute) | + +The `NestedObject` field must be defined, which represents the [object value type](/terraform/plugin/framework/handling-data/types/object) of every element of the list. + +In this example, a resource schema defines a top level required map nested attribute named `example_attribute` with a required string attribute named `attr`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.MapNestedAttribute{ + NestedObject: schema.NestedAttributeOjbect{ + Attributes: map[string]schema.Attribute{ + "attr": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Map` of `types.Object` where the `types.Object` is a mapping of `attr` to `types.String`. + +A nested attribute type may itself contain further collection or nested attribute types, if necessary. + +In this example, a resource schema defines a top level required map nested attribute named `example_attribute` with a required list of strings attribute named `attr1` and an optional single nested attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.MapNestedAttribute{ + NestedObject: schema.NestedAttributeOjbect{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ /* ... */ }, + Optional: true, + // ... potentially other fields ... + }, + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Map` of `types.Object` where the `types.Object` is a mapping of `attr1` to `types.List` of `types.String` and `attr2` to `types.Object`. + +### Configurability + + + +Only the map nested attribute itself is defined by the `schema.MapNestedAttribute` configurability fields. Nested attributes must define their own configurability fields within each attribute definition. + + + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`mapdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.Map)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault#StaticValue): Define a static list default value for the attribute. + +The [`mapplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`mapvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator) package within that module has map attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [map type](/terraform/plugin/framework/handling-data/types/map#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [map type](/terraform/plugin/framework/handling-data/types/map#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/map.mdx b/website/docs/plugin/framework/handling-data/attributes/map.mdx new file mode 100644 index 000000000..552d50e6f --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/map.mdx @@ -0,0 +1,147 @@ +--- +page_title: 'Plugin Development - Framework: Map Attribute' +description: >- + Learn the map attribute type in the provider development framework. +--- + +# Map Attribute + +Map attributes store a mapping of arbitrary string keys to values of single element type. Values are represented by a [map type](/terraform/plugin/framework/handling-data/types/map) in the framework, containing elements of the element type. + +In this Terraform configuration example, a map of string attribute named `example_attribute` is set to the mapped values of `"key1"` to `"value1"` and `"key2"` to `"value2"`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = { + "key1" = "value1" + "key2" = "value2" + } +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a map value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.MapAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#MapAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.MapAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#MapAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.MapAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#MapAttribute) | + +The `ElementType` field must be defined, which represents the single [value type](/terraform/plugin/framework/handling-data/types) of every element of the map. + +In this example, a resource schema defines a top level required map of strings attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.MapAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +An element type may itself contain further collection types, if necessary. + +In this example, a resource schema defines a top level required map of map of strings attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.MapAttribute{ + ElementType: types.MapType{ + ElemType: types.StringType, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the map value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [map type](/terraform/plugin/framework/handling-data/types/map). Refer to the collection attribute type documentation for additional details. + +If the map value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value according to the [map type](/terraform/plugin/framework/handling-data/types/map). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`mapdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.Map)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault#StaticValue): Define a static map default value for the attribute. + +The [`mapplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`mapvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator) package within that module has map attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [map type](/terraform/plugin/framework/handling-data/types/map#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [map type](/terraform/plugin/framework/handling-data/types/map#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/number.mdx b/website/docs/plugin/framework/handling-data/attributes/number.mdx new file mode 100644 index 000000000..20326809f --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/number.mdx @@ -0,0 +1,126 @@ +--- +page_title: 'Plugin Development - Framework: Number Attribute' +description: >- + Learn the number attribute type in the provider development framework. +--- + +# Number Attribute + + + +Use [Float64 Attribute](/terraform/plugin/framework/handling-data/attributes/float64) for 64-bit floating point numbers. Use [Int64 Attribute](/terraform/plugin/framework/handling-data/attributes/int64) for 64-bit integer numbers. + + + +Number attributes store an arbitrary precision (generally over 64-bit, up to 512-bit) number. Values are represented by a [number type](/terraform/plugin/framework/handling-data/types/number) in the framework. + +In this Terraform configuration example, an number attribute named `example_attribute` is set to a value greater than 64 bits: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = pow(2, 64) + 1 +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a number value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.NumberAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#NumberAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.NumberAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#NumberAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.NumberAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#NumberAttribute) | + +In this example, a resource schema defines a top level required number attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.NumberAttribute{ + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the string value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [number type](/terraform/plugin/framework/handling-data/types/number). Refer to the collection attribute type documentation for additional details. + +If the string value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value according to the [number type](/terraform/plugin/framework/handling-data/types/number). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`numberdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/numberdefault) package defines common use case `Default` implementations: + +- [`StaticNumber(number)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/numberdefault#StaticNumber): Define a static number default value for the attribute. + +The [`numberplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/numberplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/numberplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/numberplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/numberplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/numberplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`numbervalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/numbervalidator) package within that module has number attribute validators such as minimum, maximum, and defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [number type](/terraform/plugin/framework/handling-data/types/number#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [number type](/terraform/plugin/framework/handling-data/types/number#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/object.mdx b/website/docs/plugin/framework/handling-data/attributes/object.mdx new file mode 100644 index 000000000..047ea8d09 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/object.mdx @@ -0,0 +1,181 @@ +--- +page_title: 'Plugin Development - Framework: Object Attribute' +description: >- + Learn the object attribute type in the provider development framework. +--- + +# Object Attribute + + + +Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) instead of object attribute types where possible. Object attributes have limited utility as they can only define type information. A [single nested attribute type](/terraform/plugin/framework/handling-data/attributes/single-nested) supports the same configuration syntax as an object while each nested attribute can be fully defined in terms of configurability, validation, etc. + + + +Object attributes are a single structure mapping explicit attribute names to type definitions. Values are represented by a [object type](/terraform/plugin/framework/handling-data/types/object) in the framework, containing sub-attribute values of the mapped types. + +In this Terraform configuration example, an object attribute named `example_attribute` is set to the mapped values of `attr1` to `"value1"` and `attr2` to `123`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = { + attr1 = "value1" + attr2 = 123 + } +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a map value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ObjectAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ObjectAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ObjectAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ObjectAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ObjectAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ObjectAttribute) | + +The `AttributeTypes` field must be defined, which represents the mapping of explicit string object attribute names to [value types](/terraform/plugin/framework/handling-data/types). + +In this example, a resource schema defines a top level required object attribute named `example_attribute` with a string sub-attribute named `attr1` and integer sub-attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.ObjectAttribute{ + AttributeTypes: map[string]attr.Type{ + "attr1": types.StringType, + "attr2": types.Int64Type, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +A sub-attribute type may itself contain further collection types, if necessary. + +In this example, a resource schema defines a top level required object attribute named `example_attribute` with a list of strings sub-attribute named `attr1` and integer sub-attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.ObjectAttribute{ + AttributeTypes: map[string]attr.Type{ + "attr1": types.ListType{ + ElemType: types.StringType, + }, + "attr2": types.Int64Type, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the object value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [object type](/terraform/plugin/framework/handling-data/types/object). Refer to the collection attribute type documentation for additional details. + +### Configurability + + + +Only the object attribute itself, not individual sub-attributes, can define its configurability. Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) for full control of nested attribute capabilities. + + + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + + + +Only the object attribute itself, not individual sub-attributes, can define deprecation. Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) for full control of nested attribute capabilities. + + + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + + + +Only the object attribute itself, not individual sub-attributes, can define its description. Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) for full control of nested attribute capabilities. + + + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`objectdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.Object)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault#StaticValue): Define a static object default value for the attribute. + +The [`objectplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + + + +Only the object attribute itself, not individual sub-attributes, can define its sensitivity. Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) for full control of nested attribute capabilities. + + + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`objectvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator) package within that module has map attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [object type](/terraform/plugin/framework/handling-data/types/object#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [object type](/terraform/plugin/framework/handling-data/types/object#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/set-nested.mdx b/website/docs/plugin/framework/handling-data/attributes/set-nested.mdx new file mode 100644 index 000000000..43c7073ae --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/set-nested.mdx @@ -0,0 +1,175 @@ +--- +page_title: 'Plugin Development - Framework: Set Nested Attribute' +description: >- + Learn the set nested attribute type in the provider development framework. +--- + +# Set Nested Attribute + +Set nested attributes store a unique, unordered collection of nested objects. Values are represented by a [set type](/terraform/plugin/framework/handling-data/types/set) in the framework, containing elements of [object type](/terraform/plugin/framework/handling-data/types/object). + +In this Terraform configuration example, a set nested attribute named `example_attribute` is set to the unordered object values of `attr` to `"one"` and `attr` to `"two"`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = [ + { + attr = "one" + }, + { + attr = "two" + }, + ] +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a set nested value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SetNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SetNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SetNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SetNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SetNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SetNestedAttribute) | + +The `NestedObject` field must be defined, which represents the [object value type](/terraform/plugin/framework/handling-data/types/object) of every element of the set. + +In this example, a resource schema defines a top level required set nested attribute named `example_attribute` with a required string attribute named `attr`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.SetNestedAttribute{ + NestedObject: schema.NestedAttributeOjbect{ + Attributes: map[string]schema.Attribute{ + "attr": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Set` of `types.Object` where the `types.Object` is a mapping of `attr` to `types.String`. + +A nested attribute type may itself contain further collection or nested attribute types, if necessary. + +In this example, a resource schema defines a top level required set nested attribute named `example_attribute` with a required list of strings attribute named `attr1` and an optional single nested attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.SetNestedAttribute{ + NestedObject: schema.NestedAttributeOjbect{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ /* ... */ }, + Optional: true, + // ... potentially other fields ... + }, + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Set` of `types.Object` where the `types.Object` is a mapping of `attr1` to `types.List` of `types.String` and `attr2` to `types.Object`. + +### Configurability + + + +Only the set nested attribute itself is defined by the `schema.SetNestedAttribute` configurability fields. Nested attributes must define their own configurability fields within each attribute definition. + + + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`setdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.List)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault#StaticValue): Define a static set default value for the attribute. + +The [`setplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`setvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/setvalidator) package within that module has set attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [set type](/terraform/plugin/framework/handling-data/types/set#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [set type](/terraform/plugin/framework/handling-data/types/set#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/set.mdx b/website/docs/plugin/framework/handling-data/attributes/set.mdx new file mode 100644 index 000000000..454557d64 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/set.mdx @@ -0,0 +1,144 @@ +--- +page_title: 'Plugin Development - Framework: Set Attribute' +description: >- + Learn the set attribute type in the provider development framework. +--- + +# Set Attribute + +Set attributes store an unique, unordered collection of single element type. Values are represented by a [set type](/terraform/plugin/framework/handling-data/types/set) in the framework, containing elements of the element type. + +In this Terraform configuration example, a set of string attribute named `example_attribute` is set to the unordered values `"one"` and `"two"`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = ["one", "two"] +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a set value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SetAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SetAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SetAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SetAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SetAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SetAttribute) | + +The `ElementType` field must be defined, which represents the single [value type](/terraform/plugin/framework/handling-data/types) of every element of the set. + +In this example, a resource schema defines a top level required set of strings attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.SetAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +An element type may itself contain further collection types, if necessary. + +In this example, a resource schema defines a top level required set of set of strings attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.SetAttribute{ + ElementType: types.SetType{ + ElemType: types.StringType, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the set value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [set type](/terraform/plugin/framework/handling-data/types/set). Refer to the collection attribute type documentation for additional details. + +If the set value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value according to the [set type](/terraform/plugin/framework/handling-data/types/set). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`setdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.Set)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault#StaticValue): Define a static set default value for the attribute. + +The [`setplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`setvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/setvalidator) package within that module has set attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [set type](/terraform/plugin/framework/handling-data/types/set#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [set type](/terraform/plugin/framework/handling-data/types/set#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/single-nested.mdx b/website/docs/plugin/framework/handling-data/attributes/single-nested.mdx new file mode 100644 index 000000000..f1496e80a --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/single-nested.mdx @@ -0,0 +1,171 @@ +--- +page_title: 'Plugin Development - Framework: Single Nested Attribute' +description: >- + Learn the single nested attribute type in the provider development framework. +--- + +# Single Nested Attribute + +Single nested attributes are a single structure mapping explicit attribute names to nested attribute definitions. Values are represented by a [object type](/terraform/plugin/framework/handling-data/types/object) in the framework, containing nested attribute values of the mapped attributes. + +In this Terraform configuration example, a single nested attribute named `example_attribute` is set to the mapped values of `attr1` to `"value1"` and `attr2` to `123`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = { + attr1 = "value1" + attr2 = 123 + } +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a single nested value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SingleNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SingleNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SingleNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SingleNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SingleNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SingleNestedAttribute) | + +In most use cases, the `Attributes` field should be defined, which represents the mapping of explicit string attribute names to nested attributes. + +In this example, a resource schema defines a top level required single nested attribute named `example_attribute` with a required string attribute named `attr1` and optional integer attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.Int64Attribute{ + Optional: true, + // ... potentially other fields ... + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Object` with a mapping of `attr1` to `types.String` and `attr2` to `types.Int64`. + +A nested attribute type may itself contain further collection or nested attribute types, if necessary. + +In this example, a resource schema defines a top level required single nested attribute named `example_attribute` with a required list of strings attribute named `attr1` and an optional single attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ /* ... */ }, + Optional: true, + // ... potentially other fields ... + }, + }, + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Object` with a mapping of `attr1` to `types.List` of `types.String` and `attr2` to `types.Object`. + +### Configurability + + + +Only the single nested attribute itself is defined by the `schema.SingleNestedAttribute` configurability fields. Nested attributes must define their own configurability fields within each attribute definition. + + + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`objectdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.Object)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault#StaticValue): Define a static object default value for the attribute. + +The [`objectplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`objectvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator) package within that module has object attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [object type](/terraform/plugin/framework/handling-data/types/object#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [object type](/terraform/plugin/framework/handling-data/types/object#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/attributes/string.mdx b/website/docs/plugin/framework/handling-data/attributes/string.mdx new file mode 100644 index 000000000..8c5f5a2f2 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/attributes/string.mdx @@ -0,0 +1,128 @@ +--- +page_title: 'Plugin Development - Framework: String Attribute' +description: >- + Learn the string attribute type in the provider development framework. +--- + +# String Attribute + +String attributes store a collection of UTF-8 encoded bytes. Values are represented by a [string type](/terraform/plugin/framework/handling-data/types/string) in the framework. + +In this Terraform configuration example, a string attribute named `example_attribute` is set to the value `terraform`: + +```hcl +resource "examplecloud_thing" "example" { + example_attribute = "terraform" +} +``` + +## Schema Definition + +Use one of the following attribute types to directly add a string value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.StringAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#StringAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.StringAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#StringAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.StringAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#StringAttribute) | + +In this example, a resource schema defines a top level required string attribute named `example_attribute`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_attribute": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +If the string value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field according to the [string type](/terraform/plugin/framework/handling-data/types/string). Refer to the collection attribute type documentation for additional details. + +If the string value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttrTypes` map value according to the [string type](/terraform/plugin/framework/handling-data/types/string). Refer to the object attribute type documentation for additional details. + +### Configurability + +At least one of the `Computed`, `Optional`, or `Required` fields must be set to `true`. This defines how Terraform and the framework should expect data to set, whether the value is from the practitioner configuration or from the provider logic, such as API response value. + +The acceptable behaviors of these configurability options are: + +- `Required` only: The value must be practitioner configured to an eventually known value (not null), otherwise the framework will automatically raise an error diagnostic for the missing value. +- `Optional` only: The value may be practitioner configured to a known value or null. +- `Optional` and `Computed`: The value may be practitioner configured or the value may be set in provider logic when the practitioner configuration is null. +- `Computed` only: The value will be set in provider logic and any practitioner configuration causes the framework to automatically raise an error diagnostic for the unexpected configuration value. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +#### Common Use Case Types + +HashiCorp provides additional Go modules which contain custom string type implementations covering common use cases with validation and semantic equality logic: + +- [`terraform-plugin-framework-jsontypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-jsontypes): JSON encoded strings, such as exact byte strings and normalized strings +- [`terraform-plugin-framework-nettypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-nettypes): Networking strings, such as IPv4 addresses, IPv6 addresses, and CIDRs +- [`terraform-plugin-framework-timetypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-timetypes): Timestamp strings, such as RFC3339 + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`stringdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault) package defines common use case `Default` implementations: + +- [`StaticString(string)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault#StaticString): Define a static string default value for the attribute. + +The [`stringplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Sensitive + +Set the `Sensitive` field if the attribute value should always be considered [sensitive data](/terraform/language/state/sensitive-data). In Terraform, this will generally mask the value in practitioner output. This setting cannot be conditionally set and does not impact how data is stored in the state. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`stringvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator) package within that module has string attribute validators such as length, regular expression pattern, and defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [string type](/terraform/plugin/framework/handling-data/types/string#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [string type](/terraform/plugin/framework/handling-data/types/string#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/blocks.mdx b/website/docs/plugin/framework/handling-data/blocks.mdx deleted file mode 100644 index e202f5001..000000000 --- a/website/docs/plugin/framework/handling-data/blocks.mdx +++ /dev/null @@ -1,209 +0,0 @@ ---- -page_title: 'Plugin Development - Framework: Handling Data - Blocks' -description: >- - Blocks. ---- - -# Blocks - -The Terraform language uses a block as a container for other attributes and blocks. Terraform implements many top level blocks, such as `provider` and `resource`, while providers can implement nested blocks in their schema to enable practitioners to configure data. - --> Use [nested attributes](/terraform/plugin/framework/handling-data/attributes#nested-attributes) for new schema implementations. Block support is mainly for migrating prior SDK-based providers. - -In this example, the Terraform-defined `resource` block contains a provider-defined `ami` attribute and `network_interface` block. - -```hcl -resource "aws_instance" "example" { - ami = "abc123" - - network_interface { - # ... - } -} -``` - -The configuration syntax for a provider-defined block is a type (block name) and the body is delimited by the `{` and `}` characters. Each block has an associated nesting mode, which declares whether a block is repeatable. The available nesting modes are: - -- List: Ordered collection of objects -- Set: Unordered collection of objects -- Single: One object - -For list and set blocks, configurations can implement [`dynamic` block expressions](/terraform/language/expressions/dynamic-blocks) to reduce hardcoded block values. - -## Terraform Configuration - -Use the following syntax in Terraform configuration for nested blocks: - -```hcl -resource "example_resource" "example" { - list_nested_block { - bool_attribute = true - float64_attribute = 1234.5 - int64_attribute = 9223372036854775807 - list_attribute = ["list-element", "list-element"] - list_nested_nested_block { - bool_attribute = true - } - list_nested_nested_block { - bool_attribute = false - } - } - list_nested_block { - bool_attribute = true - float64_attribute = 1234.5 - int64_attribute = 9223372036854775807 - list_attribute = ["list-element", "list-element"] - list_nested_nested_block { - bool_attribute = true - } - list_nested_nested_block { - bool_attribute = false - } - } - - set_nested_block { - map_attribute = { "map-key-1" : "map-value-1" } - number_attribute = 1.79769313486231570814527423731704356798070e+1000 - object_attribute = { - bool_attribute = true - float64_attribute = 1234.5 - int64_attribute = 9223372036854775807 - list_attribute = ["obj-list-element", "obj-list-element"] - map_attribute = { "obj-map-key-1" : "obj-map-value-1" } - number_attribute = 1.79769313486231570814527423731704356798070e+1000 - set_attribute = ["obj-set-element-1", "obj-set-element-2"] - string_attribute = "obj-string" - } - set_attribute = ["set-element-1", "set-element-2"] - set_nested_nested_block { - bool_attribute = true - } - set_nested_nested_block { - bool_attribute = false - } - } - set_nested_block { - map_attribute = { "map-key-1" : "map-value-1" } - number_attribute = 1.79769313486231570814527423731704356798070e+1000 - object_attribute = { - bool_attribute = false - float64_attribute = 1234.5 - int64_attribute = 9223372036854775807 - list_attribute = ["obj-list-element", "obj-list-element"] - map_attribute = { "obj-map-key-1" : "obj-map-value-1" } - number_attribute = 1.79769313486231570814527423731704356798070e+1000 - set_attribute = ["obj-set-element-1", "obj-set-element-2"] - string_attribute = "obj-string" - } - set_attribute = ["set-element-1", "set-element-2"] - set_nested_nested_block { - bool_attribute = true - } - set_nested_nested_block { - bool_attribute = false - } - } - - single_nested_block { - bool_attribute = true - float64_attribute = 1234.5 - } -} -``` - -## Schema - -Define nested blocks in the schema as follows: - -```go -func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - Blocks: map[string]schema.Block{ - "list_nested_block": schema.ListNestedBlock{ - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "bool_attribute": schema.BoolAttribute{ - Optional: true, - }, - "float64_attribute": schema.Float64Attribute{ - Optional: true, - }, - - "int64_attribute": schema.Int64Attribute{ - Optional: true, - }, - "list_attribute": schema.ListAttribute{ - Optional: true, - ElementType: types.StringType, - }, - }, - Blocks: map[string]schema.Block{ - "list_nested_nested_block": schema.ListNestedBlock{ - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "bool_attribute": schema.BoolAttribute{ - Optional: true, - }, - }, - }, - }, - }, - }, - }, - - "set_nested_block": schema.SetNestedBlock{ - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "map_attribute": schema.MapAttribute{ - Optional: true, - ElementType: types.StringType, - }, - "number_attribute": schema.NumberAttribute{ - Optional: true, - }, - "object_attribute": schema.ObjectAttribute{ - Optional: true, - AttributeTypes: map[string]attr.Type{ - "bool_attribute": types.BoolType, - "float64_attribute": types.Float64Type, - "int64_attribute": types.Int64Type, - "list_attribute": types.ListType{ElemType: types.StringType}, - "map_attribute": types.MapType{ElemType: types.StringType}, - "number_attribute": types.NumberType, - "set_attribute": types.ListType{ElemType: types.StringType}, - "string_attribute": types.StringType, - }, - }, - "set_attribute": schema.SetAttribute{ - Optional: true, - ElementType: types.StringType, - }, - }, - Blocks: map[string]schema.Block{ - "set_nested_nested_block": schema.SetNestedBlock{ - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "bool_attribute": schema.BoolAttribute{ - Optional: true, - }, - }, - }, - }, - }, - }, - }, - - "single_nested_block": schema.SingleNestedBlock{ - Attributes: map[string]schema.Attribute{ - "bool_attribute": schema.BoolAttribute{ - Optional: true, - }, - "float64_attribute": schema.Float64Attribute{ - Optional: true, - }, - }, - }, - }, - } -} -``` diff --git a/website/docs/plugin/framework/handling-data/blocks/index.mdx b/website/docs/plugin/framework/handling-data/blocks/index.mdx new file mode 100644 index 000000000..f9b37d1d8 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/blocks/index.mdx @@ -0,0 +1,25 @@ +--- +page_title: 'Plugin Development - Framework: Blocks' +description: >- + Learn the block types in the provider development framework. Blocks + are containers for nested attributes and blocks in a resource, data source, or + provider schema. +--- + +# Blocks + + + +Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) instead of block types for new schema implementations. Block support is mainly for migrating legacy SDK-based providers. + + + +Blocks are containers for other attributes and blocks in resource, data source, or provider [schemas](/terraform/plugin/framework/handling-data/schemas). Every block has an associated [value type](/terraform/plugin/framework/handling-data/types), which describes the kind of data the block holds. Blocks also can describe value plan modifiers (resources only) and value validators in addition to those defined by the value type. + +## Available Block Types + +| Block Type | Use Case | +|----------------|----------| +| [List Nested](/terraform/plugin/framework/handling-data/blocks/list-nested) | Ordered collection of structures of attributes/blocks | +| [Set Nested](/terraform/plugin/framework/handling-data/blocks/set-nested) | Unordered, unique collection of structures of attributes/blocks | +| [Single Nested](/terraform/plugin/framework/handling-data/blocks/single-nested) | Single structure of attributes/blocks | diff --git a/website/docs/plugin/framework/handling-data/blocks/list-nested.mdx b/website/docs/plugin/framework/handling-data/blocks/list-nested.mdx new file mode 100644 index 000000000..bf7212809 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/blocks/list-nested.mdx @@ -0,0 +1,167 @@ +--- +page_title: 'Plugin Development - Framework: List Nested Block' +description: >- + Learn the list nested block type in the provider development framework. +--- + +# List Nested Block + + + +Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) instead of block types for new schema implementations. Block support is mainly for migrating legacy SDK-based providers. + + + +List nested blocks are an ordered collection of structures mapping explicit attribute names to nested attribute and block definitions. Values are represented by a [list type](/terraform/plugin/framework/handling-data/types/list) in the framework, containing [object type](/terraform/plugin/framework/handling-data/types/object) of the mapped attributes and blocks. + +In this Terraform configuration example, a list nested block named `example_block` is set to an ordered collection of an object value of `attr1` to `"value1"` and `attr2` to `123` and an object value of `attr1` to `"value2"` and `attr2` to `456`: + +```hcl +resource "examplecloud_thing" "example" { + example_block { + attr1 = "value1" + attr2 = 123 + } + + example_block { + attr1 = "value2" + attr2 = 456 + } +} +``` + +## Schema Definition + + + +Blocks can only be defined on schemas or nested blocks within a schema, not underneath an attribute or nested attribute. + + + +Use one of the following block types to directly add a list nested value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [block type](/terraform/plugin/framework/handling-data/blocks): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ListNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ListNestedBlock) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ListNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ListNestedBlock) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ListNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ListNestedBlock) | + +The `NestedObject` field must be defined, which represents the [object value type](/terraform/plugin/framework/handling-data/types/object) of every element of the list. + +In this example, a resource schema defines a top level list nested block named `example_block` with a required string attribute named `attr1` and optional integer attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_block": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.Int64Attribute{ + Optional: true, + // ... potentially other fields ... + }, + }, + }, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as `types.List` of `types.Object` with a mapping of `attr1` to `types.String` and `attr2` to `types.Int64`. + +A block type may itself contain further collection or nested attribute/block types, if necessary. + +In this example, a resource schema defines a top level list nested block named `example_block` with a required list of strings attribute named `attr` and a single nested block named `block`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_block": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "attr": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + }, + Blocks: map[string]schema.Block{ + "block": schema.ListNestedBlock{ /* ... */ }, + }, + }, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.List` of `types.Object` with a mapping of `attr` to `types.List` of `types.String` and `block` to `types.Object`. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`listdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.List)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault#StaticValue): Define a static list default value for the attribute. + +The [`listplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`listvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/listvalidator) package within that module has list attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [list type](/terraform/plugin/framework/handling-data/types/list#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [list type](/terraform/plugin/framework/handling-data/types/list#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/blocks/set-nested.mdx b/website/docs/plugin/framework/handling-data/blocks/set-nested.mdx new file mode 100644 index 000000000..ee6670825 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/blocks/set-nested.mdx @@ -0,0 +1,167 @@ +--- +page_title: 'Plugin Development - Framework: Set Nested Block' +description: >- + Learn the set nested block type in the provider development framework. +--- + +# Set Nested Block + + + +Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) instead of block types for new schema implementations. Block support is mainly for migrating legacy SDK-based providers. + + + +Set nested blocks are an unique, unordered collection of structures mapping explicit attribute names to nested attribute and block definitions. Values are represented by a [set type](/terraform/plugin/framework/handling-data/types/set) in the framework, containing [object type](/terraform/plugin/framework/handling-data/types/object) of the mapped attributes and blocks. + +In this Terraform configuration example, a set nested block named `example_block` is set to an unordered collection of an object value of `attr1` to `"value1"` and `attr2` to `123` and an object value of `attr1` to `"value2"` and `attr2` to `456`: + +```hcl +resource "examplecloud_thing" "example" { + example_block { + attr1 = "value1" + attr2 = 123 + } + + example_block { + attr1 = "value2" + attr2 = 456 + } +} +``` + +## Schema Definition + + + +Blocks can only be defined on schemas or nested blocks within a schema, not underneath an attribute or nested attribute. + + + +Use one of the following block types to directly add a list nested value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [block type](/terraform/plugin/framework/handling-data/blocks): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SetNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SetNestedBlock) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SetNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SetNestedBlock) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SetNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SetNestedBlock) | + +The `NestedObject` field must be defined, which represents the [object value type](/terraform/plugin/framework/handling-data/types/object) of every element of the set. + +In this example, a resource schema defines a top level set nested block named `example_block` with a required string attribute named `attr1` and optional integer attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_block": schema.SetNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.Int64Attribute{ + Optional: true, + // ... potentially other fields ... + }, + }, + }, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as `types.Set` of `types.Object` with a mapping of `attr1` to `types.String` and `attr2` to `types.Int64`. + +A block type may itself contain further collection or nested attribute/block types, if necessary. + +In this example, a resource schema defines a top level set nested block named `example_block` with a required list of strings attribute named `attr` and a single nested block named `block`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_block": schema.SetNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "attr": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + }, + Blocks: map[string]schema.Block{ + "block": schema.SetNestedBlock{ /* ... */ }, + }, + }, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Set` of `types.Object` with a mapping of `attr` to `types.List` of `types.String` and `block` to `types.Object`. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`setdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.Set)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault#StaticValue): Define a static list default value for the attribute. + +The [`setplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`setvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/setvalidator) package within that module has set attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [set type](/terraform/plugin/framework/handling-data/types/set#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [set type](/terraform/plugin/framework/handling-data/types/set#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/blocks/single-nested.mdx b/website/docs/plugin/framework/handling-data/blocks/single-nested.mdx new file mode 100644 index 000000000..768feb553 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/blocks/single-nested.mdx @@ -0,0 +1,158 @@ +--- +page_title: 'Plugin Development - Framework: Single Nested Block' +description: >- + Learn the single nested block type in the provider development framework. +--- + +# Single Nested Block + + + +Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) instead of block types for new schema implementations. Block support is mainly for migrating legacy SDK-based providers. + + + +Single nested blocks are a single structure mapping explicit attribute names to nested attribute and block definitions. Values are represented by a [object type](/terraform/plugin/framework/handling-data/types/object) in the framework, containing nested attribute values of the mapped attributes and blocks. + +In this Terraform configuration example, a single nested block named `example_block` is set to the mapped values of `attr1` to `"value1"` and `attr2` to `123`: + +```hcl +resource "examplecloud_thing" "example" { + example_block { + attr1 = "value1" + attr2 = 123 + } +} +``` + +## Schema Definition + + + +Blocks can only be defined on schemas or nested blocks within a schema, not underneath an attribute or nested attribute. + + + +Use one of the following block types to directly add a single nested value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [block type](/terraform/plugin/framework/handling-data/blocks): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SingleNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SingleNestedBlock) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SingleNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SingleNestedBlock) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SingleNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SingleNestedBlock) | + +In most use cases, the `Attributes` or `Blocks` field should be defined, which represents the mapping of explicit string attribute names to nested attributes and/or blocks. + +In this example, a resource schema defines a top level single nested block named `example_block` with a required string attribute named `attr1` and optional integer attribute named `attr2`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_block": schema.SingleNestedBlock{ + Attributes: map[string]schema.Attribute{ + "attr1": schema.StringAttribute{ + Required: true, + // ... potentially other fields ... + }, + "attr2": schema.Int64Attribute{ + Optional: true, + // ... potentially other fields ... + }, + }, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Object` with a mapping of `attr1` to `types.String` and `attr2` to `types.Int64`. + +A block type may itself contain further collection or nested attribute/block types, if necessary. + +In this example, a resource schema defines a top level single nested block named `example_block` with a required list of strings attribute named `attr` and a single nested block named `block`: + +```go +func (r ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "example_block": schema.SingleNestedBlock{ + Attributes: map[string]schema.Attribute{ + "attr": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + // ... potentially other fields ... + }, + }, + Blocks: map[string]schema.Block{ + "block": schema.SingleNestedBlock{ /* ... */ }, + }, + // ... potentially other fields ... + }, + // ... potentially other attributes ... + }, + } +} +``` + +Its [value type](/terraform/plugin/framework/handling-data/types) would be represented as a `types.Object` with a mapping of `attr` to `types.List` of `types.String` and `block` to `types.Object`. + +### Custom Types + +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. These implementations use the `CustomType` field in the attribute type. + +Refer to [Custom Types](/terraform/plugin/framework/handling-data/types/custom) for further details on creating provider-defined types and values. + +### Deprecation + +Set the `DeprecationMessage` field to a practitioner-focused message for how to handle the deprecation. The framework will automatically raise a warning diagnostic with this message if the practitioner configuration contains a known value for the attribute. Terraform version 1.2.7 and later will raise a warning diagnostic in certain scenarios if the deprecated attribute value is referenced elsewhere in a practitioner configuration. The framework [deprecations](/terraform/plugin/framework/deprecations) documentation fully describes the recommended practices for deprecating an attribute or resource. + +Some practitioner-focused examples of a deprecation message include: + +- Configure `other_attribute` instead. This attribute will be removed in the next major version of the provider. +- Remove this attribute's configuration as it no longer is used and the attribute will be removed in the next major version of the provider. + +### Description + +The framework provides two description fields, `Description` and `MarkdownDescription`, which various tools use to show additional information about an attribute and its intended purpose. This includes, but is not limited to, [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) for automated provider documentation generation and [`terraform-ls`](https://github.com/hashicorp/terraform-ls) for Terraform configuration editor integrations. + +### Plan Modification + + + +Only managed resources implement this concept. + + + +The framework provides two plan modification fields for managed resource attributes, `Default` and `PlanModifiers`, which define resource and attribute value planning behaviors. The resource [default](/terraform/plugin/framework/resources/default) and [plan modification](/terraform/plugin/framework/resources/plan-modification) documentation covers these features more in-depth. + +#### Common Use Case Plan Modification + +The [`objectdefault`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault) package defines common use case `Default` implementations: + +- [`StaticValue(types.Object)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault#StaticValue): Define a static object default value for the attribute. + +The [`objectplanmodifier`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier) package defines common use case `PlanModifiers` implementations: + +- [`RequiresReplace()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplace): Marks the resource for replacement if the resource is being updated and the plan value does not match the prior state value. +- [`RequiresReplaceIf()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplaceIf): Similar to `RequiresReplace()`, but also checks if a given function returns true. +- [`RequiresReplaceIfConfigured()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#RequiresReplaceIfConfigured): Similar to `RequiresReplace()`, but also checks if the configuration value is not null. +- [`UseStateForUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier#UseStateForUnknown): Copies a known prior state value into the planned value. Use this when it is known that an unconfigured value will remain the same after a resource update. + +### Validation + +Set the `Validators` field to define [validation](/terraform/plugin/framework/validation#attribute-validation). This validation logic is ran in addition to any validation contained within a [custom type](#custom-types). + +#### Common Use Case Validators + +HashiCorp provides the additional [`terraform-plugin-framework-validators`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators) Go module which contains validation logic for common use cases. The [`objectvalidator`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator) package within that module has object attribute validators such as defining conflicting attributes. + +## Accessing Values + +The [accessing values](/terraform/plugin/framework/handling-data/accessing-values) documentation covers general methods for reading [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data, which is necessary before accessing an attribute value directly. The [object type](/terraform/plugin/framework/handling-data/types/object#accessing-values) documentation covers methods for interacting with the attribute value itself. + +## Setting Values + +The [object type](/terraform/plugin/framework/handling-data/types/object#setting-values) documentation covers methods for creating or setting the appropriate value. The [writing data](/terraform/plugin/framework/handing-data/writing-state) documentation covers general methods for writing [schema](/terraform/plugin/framework/handling-data/schemas) (plan and state) data, which is necessary afterwards. diff --git a/website/docs/plugin/framework/handling-data/conversion-rules.mdx b/website/docs/plugin/framework/handling-data/conversion-rules.mdx deleted file mode 100644 index 0d9cba2a3..000000000 --- a/website/docs/plugin/framework/handling-data/conversion-rules.mdx +++ /dev/null @@ -1,241 +0,0 @@ ---- -page_title: 'Plugin Development - Framework: Conversion Rules' -description: |- - Converting from Framework Types to Go types and from Go types - to Framework types. ---- - -# Conversion Rules - -## Converting from Framework Types to Go Types - -!> **Warning:** It can be tempting to use Go types instead of `attr.Value` -implementations when the provider doesn't care about the distinction between an -empty value, unknown, and null. But if Terraform has a null or unknown value -and the provider asks the framework to store it in a type that can't hold it, -[`Get`](/terraform/plugin/framework/handling-data/accessing-values#get-the-entire-configuration-plan-or-state) -will return an error. Make sure the types you are using can hold the -values they might contain! - -### String - -Strings can be automatically converted to Go's `string` type (or any aliases of -it, like `type MyString string`) as long as the string value is not null or -unknown. - -### Number - -Numbers can be automatically converted to the following numeric types (or any -aliases of them, like `type MyNumber int`) as long as the number value is not -null or unknown: - -* `int`, `int8`, `int16`, `int32`, `int64` -* `uint`, `uint8`, `uint16`, `uint32`, `uint64` -* `float32`, `float64` -* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float) - -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. - -### Boolean - -Booleans can be automatically converted to Go's `bool` type (or any aliases of -it, like `type MyBoolean bool`) as long as the boolean value is not null or -unknown. - -### List - -Lists can be automatically converted to any Go slice type (or alias of a Go -slice type, like `type MyList []string`), with the elements either being -`attr.Value` implementations or being converted according to these rules. Go -slice types are considered capable of handling null values; the slice will be -set to nil. The `Get` method will still return an error for unknown list -values. - -### Map - -Maps can be automatically converted to any Go map type with string keys (or any -alias of a Go map type with string keys, like `type MyMap map[string]int`), -with the elements either being `attr.Value` implementations or being converted -according to these rules. Go map types are considered capable of handling null -values; the map will be set to nil. The `Get` method will still return an error -for unknown map values. - -### Object - -Objects can be automatically converted to any Go struct type with that follows these constraints: - -* Every property on the struct must have a `tfsdk` struct tag. -* The `tfsdk` struct tag must name an attribute in the object that it is being - mapped to or be set to `-` to explicitly declare it does not map to an - attribute in the object. -* Every attribute in the object must have a corresponding struct tag. - -These rules help prevent typos and human error from unwittingly discarding -information by failing as early, consistently, and loudly as possible. - -Properties can either be `attr.Value` implementations or will be converted -according to these rules. - -Unknown and null objects cannot be represented as structs and will return an -error. Their attributes may contain unknown or null values if the attribute's -type can hold them. - -### Pointers - -Pointers behave exactly like the type they are referencing, except they can hold -null values. A pointer will be set to `nil` when representing a null value; -otherwise, the conversion rules for that type will apply. - -### Detected Interfaces - -[`Get`](/terraform/plugin/framework/handling-data/accessing-values#get-the-entire-configuration-plan-or-state) -detects and utilizes the following interfaces, if the target implements -them. - -#### ValueConverter - -If a value is being set on a Go type that implements the [`tftypes.ValueConverter` -interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#ValueConverter), -that interface will be delegated to to handle the conversion. - -#### Unknownable - -If the value is being set on a Go type that fills the `Unknownable` interface: - -```go -type Unknownable interface { - SetUnknown(context.Context, bool) error - SetValue(context.Context, interface{}) error - GetUnknown(context.Context) bool - GetValue(context.Context) interface{} -} -``` - -It will be considered capable of handling unknown values, and those methods -will be used to populate it and retrieve its value. The `interface{}` being -passed and retrieved will be of a type that can be passed to -[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue). - -#### Nullable - -If the value is being set on a Go type that fills the `Nullable` interface: - -```go -type Nullable interface { - SetNull(context.Context, bool) error - SetValue(context.Context, interface{}) error - GetNull(context.Context) bool - GetValue(context.Context) interface{} -} -``` - -It will be considered capable of handling null values, and those methods will -be used to populate it and retrieve its value. The `interface{}` being passed -and retrieved will be of a type that can be passed to -[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue). - -## Converting from Go Types to Framework Types - -The following is a list of schema types and the Go types they know how to -accept in [`Set`](/terraform/plugin/framework/handling-data/writing-state#replace-the-entire-state) -and [`SetAttribute`](/terraform/plugin/framework/handling-data/writing-state#set-a-single-attribute-or-block-value). - -### String - -Strings can be automatically created from Go's `string` type (or any aliases of -it, like `type MyString string`). - -### Number - -Numbers can be automatically created from the following numeric types (or any -aliases of them, like `type MyNumber int`): - -* `int`, `int8`, `int16`, `int32`, `int64` -* `uint`, `uint8`, `uint16`, `uint32`, `uint64` -* `float32`, `float64` -* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float) - -### Boolean - -Booleans can be automatically created from Go's `bool` type (or any aliases of -it, like `type MyBoolean bool`). - -### List - -Lists can be automatically created from any Go slice type (or alias of a Go -slice type, like `type MyList []string`), with the elements either being -`attr.Value` implementations or being converted according to these rules. - -### Map - -Maps can be automatically created from any Go map type with string keys (or any -alias of a Go map type with string keys, like `type MyMap map[string]int`), -with the elements either being `attr.Value` implementations or being converted -according to these rules. - -### Object - -Objects can be automatically created from any Go struct type with that follows -these constraints: - -* Every property on the struct must have a `tfsdk` struct tag. -* The `tfsdk` struct tag must name an attribute in the object that it is being -mapped to or be set to `-` to explicitly declare it does not map to an -attribute in the object. -* Every attribute in the object must have a corresponding struct tag. - -These rules help prevent typos and human error from unwittingly discarding -information by failing as early, consistently, and loudly as possible. - -Properties can either be `attr.Value` implementations or will be converted -according to these rules. - -### Pointers - -A nil pointer will be treated as a null value. Otherwise, the rules for the -type the pointer is referencing apply. - -### Detected Interfaces - -`Set` detects and utilizes the following interfaces, if the target implements -them. - -#### ValueCreator - -If a value is set on a Go type that implements the [`tftypes.ValueCreator` -interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#ValueCreator), -that interface will be delegated to to handle the conversion. - -#### Unknownable - -If a value is set on a Go type that fills the `Unknownable` interface: - -```go -type Unknownable interface { - SetUnknown(context.Context, bool) error - SetValue(context.Context, interface{}) error - GetUnknown(context.Context) bool - GetValue(context.Context) interface{} -} -``` - -It will be used to convert the value. The `interface{}` being passed and -retrieved will be of a type that can be passed to -[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue). - -#### Nullable - -If a value is set on a Go type that fills the `Nullable` interface: - -```go -type Nullable interface { - SetNull(context.Context, bool) error - SetValue(context.Context, interface{}) error - GetNull(context.Context) bool - GetValue(context.Context) interface{} -} -``` - -It will be used to convert the value. The `interface{}` being passed and -retrieved will be of a type that can be passed to -[`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue). diff --git a/website/docs/plugin/framework/handling-data/schemas.mdx b/website/docs/plugin/framework/handling-data/schemas.mdx index 673d5ddfc..a36661221 100644 --- a/website/docs/plugin/framework/handling-data/schemas.mdx +++ b/website/docs/plugin/framework/handling-data/schemas.mdx @@ -57,103 +57,6 @@ is a best practice to only alter the formatting, not the content, between the At the moment, if the `MarkdownDescription` property is set it will always be used instead of the `Description` property. It is possible that a different strategy may be employed in the future to surface descriptions to other tooling in a different format, so we recommend specifying both fields. -## Attributes - -Attributes are the main point of a schema. They are used to describe the fields -of a provider, resource, or data source. Attributes are defined as a map of -string names to definitions. - -The name should only contain lowercase -letters, numbers, and underscores. Practitioners will enter these strings in -the configuration block of the provider, resource, or data source to set a -value for that field. - -The value is the implementation details for the attribute. - -Refer to [Attributes](/terraform/plugin/framework/handling-data/attributes) for further details of the different types of attributes. - -### Required - -Setting the `Required` property to `true` indicates that the attribute is -required. Practitioners will be automatically given a validation error if they -omit the attribute in their configuration. - -Attributes that set `Required` to `true` cannot set `Optional` or `Computed` to -`true`. - -### Optional - -Setting the `Optional` property to `true` indicates that the attribute is -optional. Practitioners are free to specify that attribute or omit it, and -Terraform will not automatically generate a validation error based on the -presence or absence of that attribute. - -Attributes that set `Optional` to `true` cannot set `Required` to `true`, but -may set `Computed` to `true`, in which case the behavior of `Computed` applies, -too. - -### Computed - -Setting the `Computed` property to `true` indicates that the attribute can be -set by the provider. Any attribute that does not have `Computed` set to `true` -cannot be influenced by the provider; it can only be changed via the config or -via state refreshing. - -If `Computed` is set to `true` and `Optional` is not set to `true`, the -attribute will be considered read-only and Terraform will automatically -generate a validation error if the practitioner attempts to enter a -configuration value for that attribute. - -If `Computed` is set to `true` and `Optional` is set to `true`, Terraform will -not do any validation on the presence or absence of the value. - -If `Computed` is set to `true`, `Required` must not be set to `true`. - -Because providers don't set provider configuration values in state, provider -schemas should never set `Computed` to `true`. - -### Sensitive - -Setting the `Sensitive` property to `true` indicates to Terraform that the -value should always be considered -[sensitive](/terraform/language/state/sensitive-data). This does not at this -time add any encryption or otherwise hide the value from Terraform; see [the -documentation for SDKv2](/terraform/plugin/sdkv2/best-practices/sensitive-state) for -more information on sensitive state and Terraform. It does, however, hide the -value in Terraform's outputs and in Terraform Cloud. - -### Description - -Much like [resources, data sources, and providers can have a -description](#description), so too can individual attributes. - -### MarkdownDescription - -Much like [resources, data sources, and providers can have a markdown-formatted -description](#markdowndescription), so too can individual attributes. - -### DeprecationMessage - -Individual attributes can be deprecated similar to resources, data sources, and providers. When the `DeprecationMessage` value is a non-empty string, the framework will automatically raise a warning diagnostic to practitioners if a configuration value (known or unknown) or reference is detected for the attribute during Terraform's validation phase: - -```text -Warning: Attribute Deprecated - -{Configuration file/line information} - -{DeprecationMessage field value} -``` - -Use a practitioner actionable recommendation in `DeprecationMessage`, such as `"Configure other_attribute instead. This attribute will be removed in the next major version of the provider."` or `"Remove this attribute's configuration as it's no longer in use and the attribute will be removed in the next major version of the provider."`. - -~> **NOTE**: In Terraform 1.2.6 and earlier, a deprecation warning diagnostic is only raised for configurable (`Required` or `Optional`) attributes when a configuration value is detected. A warning diagnostic is not raised for read-only (`Computed` only) attributes when referenced. - -### Validators - -Each attribute can implement [value validation](/terraform/plugin/framework/validation), either by specifying the [`Attribute` type `Validators` field](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#Attribute.Validators) and/or by declaring a custom type in the `Type` field that [implements its own validators](/terraform/plugin/framework/validation#type-validation). Common use case validators can be found in the [terraform-plugin-framework-validators Go module](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-validators). - -During execution of the [`terraform validate`](/terraform/cli/commands/validate), [`terraform plan`](/terraform/cli/commands/plan) and [`terraform apply`](/terraform/cli/commands/apply) commands, Terraform calls the provider [`ValidateProviderConfig`](/terraform/plugin/framework/internals/rpcs#validateproviderconfig-rpc), [`ValidateResourceConfig`](/terraform/plugin/framework/internals/rpcs#validateresourceconfig-rpc) and [`ValidateDataResourceConfig`](/terraform/plugin/framework/internals/rpcs#validatedataresourceconfig-rpc) RPCs, during which [value validation](/terraform/plugin/framework/validation) takes place. - ## Unit Testing Schemas can be unit tested via each of the `schema.Schema` type `ValidateImplementation()` methods. This unit testing raises schema implementation issues more quickly in comparison to [acceptance tests](/terraform/plugin/framework/acctests), but does not replace the purpose of acceptance testing. diff --git a/website/docs/plugin/framework/handling-data/terraform-concepts.mdx b/website/docs/plugin/framework/handling-data/terraform-concepts.mdx index 85657cd62..ba73c0aef 100644 --- a/website/docs/plugin/framework/handling-data/terraform-concepts.mdx +++ b/website/docs/plugin/framework/handling-data/terraform-concepts.mdx @@ -6,48 +6,118 @@ description: >- # Terraform Concepts -Schemas specify the fields that a provider, resource or data source configuration can have. +This page describes Terraform concepts as they relate to handling data within framework-based provider code. The [What is Terraform](/terraform/intro), [Terraform language](/terraform/language), and [Plugin Development](/terraform/plugin) documentation covers more general concepts behind Terraform's workflow, its configuration, and how it interacts with providers. -The fields defined within the schema are either attributes or blocks. +## Schemas -Attributes and blocks within Terraform configuration have different syntax, either using, or omitting an equals sign in their definition, respectively. +Schemas specify the data structure and types of a provider, resource, or data source that is exposed to Terraform. This includes the configuration written by practitioners, any planning data, and the state stored by Terraform which can be referenced in other configuration. Providers, resources, and data sources have their own concept-specific types and available functionality. -Providers, resources and data sources have their own type-specific schema, which use type-specific attributes and blocks. +Each part of the data within a schema is defined as either an attribute or block. In general, attributes set values and blocks are containers for other attributes and blocks. Each have differing configuration syntax and behaviors. -The following examples use a resource but the same schema attribute and block types are also defined with the schema for providers and data sources. The examples focus on type-related information, the `Optional` field is included just to provide working examples but refer to [Schema](/terraform/plugin/framework/handling-data/schemas) for information about the other fields that can be defined within attributes and blocks. +Discover more about framework implementations of this concept in the [schema](/terraform/plugin/framework/handling-data/schemas) documentation. -## Attributes +### Attributes -Attributes are used to set values. +Attributes set values in a schema, such as a string or list. The [Terraform type system](/terraform/language/expressions/types) documentation provides a general overview of the available kinds of data within Terraform, which is similar with type system concepts available in many programming languages. However, there are subtle differences with values discussed in the [type system](#type-system) section. -| Attribute Type | Description | -|-----------------------|---------------------------------------------------------------------------------| -| BoolAttribute | Boolean values (i.e., true/false) | -| Float64Attribute | 64 bit floating point number values | -| Int64Attribute | 64 bit integer number values | -| NumberAttribute | Generic number with up to 512 bits of floating point or integer precision | -| StringAttribute | String values | -| ListAttribute | List with a single element type (e.g., types.StringType) | -| MapAttribute | Map with a single element type (e.g., types.Int64Type) | -| SetAttribute | Set with a single element type (e.g., types.BoolType) | -| ObjectAttribute | Object with only type information for underlying attributes | -| ListNestedAttribute | List containing nested objects where the object attributes can be fully defined | -| MapNestedAttribute | Map containing nested objects where the object attributes can be fully defined | -| SetNestedAttribute | Set containing nested objects where the object attributes can be fully defined | -| SingleNestedAttribute | Single object where the object attributes can be fully defined | +Discover more about the framework implementations of this concept in the [attribute](/terraform/plugin/framework/handling-data/attributes) documentation. -Refer to [Attributes - Terraform Configuration and Schema](/terraform/plugin/framework/handling-data/attributes#terraform-configuration-and-schema) for examples of Terraform configuration and schema that illustrate the usage of the various types of schema attributes. +### Blocks -## Blocks + -The Terraform language uses a block as a container for other attributes and blocks. Terraform implements many top level blocks, such as `provider` and `resource`, while providers can implement nested blocks in their schema to enable practitioners to configure data. +Use [nested attributes](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) for new schema implementations. Block support is mainly for migrating prior SDK-based providers. --> Use [nested attributes](/terraform/plugin/framework/handling-data/attributes#nested-attributes) for new schema implementations. Block support is mainly for migrating prior SDK-based providers. + -The available nesting modes are: +A block is a container for other attributes and blocks. Terraform implements many top level blocks, such as `provider` and `resource`, while a schema supports nested blocks. -- List: Ordered collection of objects -- Set: Unordered collection of objects -- Single: One object +Discover more about the framework implementations of this concept in the [block](/terraform/plugin/framework/handling-data/blocks) documentation. -Refer to [Blocks - Terraform Configuration](/terraform/plugin/framework/handling-data/blocks#terraform-configuration) for examples of Terraform configuration and schema that illustrate the usage of nested blocks. +### Schema Based Data + +Schemas provide the structures and types for representing data with Terraform. This section discusses the concepts behind the different types of data influenced by a schema. + +#### Configuration + +As part of the Terraform workflow, a practitioner writes [configuration](/terraform/language) files, which are parsed into a graph of operations by Terraform commands. The structures and types of that configuration is the most visible aspect of a schema, since a schema has a direct effect on the expected configuration syntax. + +In Terraform operations where the configuration data is available to providers, the framework typically represents this as a `Config` field in the request type. + +#### Plan + + + +Only managed resources implement this data concept. + + + +As part of the Terraform workflow, any configuration changes are planned before they are applied into [state](/terraform/language/state) so practitioners have an opportunity to review whether those anticipated changes have their intended effect. Conceptually, this data represents the merging of configuration data and any prior state data. Terraform refers to this data as the proposed new state, while the framework more generally refers to this data as the plan. + +Plan data requires careful handling to prevent unexpected Terraform errors for practitioners. The framework implements various schema concepts and logic discussed in the [resource plan modification](/terraform/plugin/framework/resources/plan-modification) documentation. In-depth documentation about Terraform requirements is available in the [Terraform Resource Instance Change Lifecycle](https://github.com/hashicorp/terraform/blob/main/docs/resource-instance-change-lifecycle.md) documentation. + +In Terraform operations where the plan data is available to providers, the framework typically represents this as a `Plan` field in the request or response type. + +#### State + + + +Only managed resources and data resources implement this data concept. + + + +As part of the Terraform workflow, any data that should be stored for configuration references or future Terraform executions must be written to the [state](/terraform/language/state). This data must exactly match any configuration data, and if applicable, any plan data with [unknown values](#unknown-values) converted to known values. + +In Terraform operations where the plan data is available to providers, the framework typically represents this as a `State` field in the request or response type. + +## Type System + +The [Terraform type system](/terraform/language/expressions/types) supports deeper functionality than the standard type systems built into programming languages. While the types in the Terraform type system are similar to what is found in most languages, values have extra metadata associated with them. The framework implements its own [types](/terraform/plugin/framework/handling-data/types) to prevent the loss of this additional metadata that cannot be represented by Go built-in types. + +Important value metadata concepts when implementing a provider include: + +- [Null values](#null-values): Absence of a value. +- [Unknown values](#unknown-values): Value that is not yet known. + +As Terraform exposes additional value metadata to providers, the framework type system will be updated. Therefore, it is always recommended to use the framework type system to ensure all Terraform value functionality is available in provider code. + +### Null Values + +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 Values + +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: + +```tf +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. diff --git a/website/docs/plugin/framework/handling-data/types/bool.mdx b/website/docs/plugin/framework/handling-data/types/bool.mdx new file mode 100644 index 000000000..0d4205b45 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/bool.mdx @@ -0,0 +1,106 @@ +--- +page_title: 'Plugin Development - Framework: Bool Type' +description: >- + Learn the bool value type in the provider development framework. +--- + +# Bool Type + +Bool types store a boolean true or false value. + +By default, strings from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.BoolType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolType) and its associated value storage type of [`types.Bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Bool). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as `*bool`. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a bool value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.BoolAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#BoolAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.BoolAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#BoolAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.BoolAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#BoolAttribute) | + +If the bool value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElemType` field to `types.BoolType` or the appropriate [custom type](#extending). + +If the bool value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttrTypes` map value to `types.BoolType` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/bool#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.Bool` in this case. + + + +Access `types.Bool` information via the following methods: + +* [`(types.Bool).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#BoolValue.IsNull): Returns true if the bool is null. +* [`(types.Bool).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#BoolValue.IsUnknown): Returns true if the bool is unknown. +* [`(types.Bool).ValueBool() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#BoolValue.ValueBool): Returns the known bool, or `false` if null or unknown. +* [`(types.Bool).ValueBoolPointer() *bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#BoolValue.ValueBoolPointer): Returns a bool pointer to a known value, `nil` if null, or a pointer to `false` if unknown. + +In this example, a bool value is checked for being null or unknown value first, before accessing its known value: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.Bool `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +// myBool now contains a Go bool with the known value +myBool := data.ExampleAttribute.ValueBool() +``` + +## Setting Values + +Call one of the following to create a `types.Bool` value: + +* [`types.BoolNull()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolNull): A null bool value. +* [`types.BoolUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolUnknown): An unknown bool value. +* [`types.BoolValue(bool)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolValue): A known value. +* [`types.BoolPointerValue(*bool)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#BoolPointerValue): A known value. + +In this example, a known bool value is created: + +```go +types.BoolValue(true) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +A Go built-in `bool`, `*bool` (only with typed `nil`, `(*bool)(nil)`), or type alias of `bool` such as `type MyStringType bool` can be used instead. + +In this example, a `bool` is directly used to set a bool attribute value: + +```go +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), true) +``` + +In this example, a `types.List` of `types.Bool` is created from a `[]bool`: + +```go +listValue, diags := types.ListValueFrom(ctx, types.BoolType, []bool{true, false}) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/custom-types.mdx b/website/docs/plugin/framework/handling-data/types/custom.mdx similarity index 100% rename from website/docs/plugin/framework/handling-data/custom-types.mdx rename to website/docs/plugin/framework/handling-data/types/custom.mdx diff --git a/website/docs/plugin/framework/handling-data/types/float64.mdx b/website/docs/plugin/framework/handling-data/types/float64.mdx new file mode 100644 index 000000000..1e6fca4e2 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/float64.mdx @@ -0,0 +1,119 @@ +--- +page_title: 'Plugin Development - Framework: Float64 Type' +description: >- + Learn the float64 value type in the provider development framework. +--- + +# Float64 Type + + + +Use [Int64 Type](/terraform/plugin/framework/handling-data/types/int64) for 64-bit integer numbers. Use [Number Attribute](/terraform/plugin/framework/handling-data/types/number) for arbitrary precision numbers. + + + +Float64 types store a 64-bit floating point number. + +By default, float64 from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.Float64Type`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Type) and its associated value storage type of [`types.Float64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as `*float64`. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a float64 value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.Float64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#Float64Attribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.Float64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#Float64Attribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.Float64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#Float64Attribute) | + +If the float64 value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElemType` field to `types.Float64Type` or the appropriate [custom type](#extending). + +If the float64 value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttrTypes` map value to `types.Float64Type` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/float64#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.Float64` in this case. + + + +Access `types.Float64` information via the following methods: + +* [`(types.Float64).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Float64Value.IsNull): Returns true if the float64 is null. +* [`(types.Float64).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Float64Value.IsUnknown): Returns true if the float64 is unknown. +* [`(types.Float64).ValueFloat64() float64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Float64Value.ValueFloat64): Returns the known float64, or `0.0` if null or unknown. +* [`(types.Float64).ValueFloat64Pointer() *float64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Float64Value.ValueFloat64Pointer): Returns a float64 pointer to a known value, `nil` if null, or a pointer to `0.0` if unknown. + +In this example, a float64 value is checked for being null or unknown value first, before accessing its known value: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.Float64 `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +// myFloat64 now contains a Go float64 with the known value +myFloat64 := data.ExampleAttribute.ValueFloat64() +``` + +## Setting Values + +Call one of the following to create a `types.Float64` value: + +* [`types.Float64Null()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Null): A null float64 value. +* [`types.Float64Unknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Unknown): An unknown float64 value. +* [`types.Float64Value(float64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64Value): A known value. +* [`types.Float64PointerValue(*float64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Float64PointerValue): A known value. + +In this example, a known float64 value is created: + +```go +types.Float64Value(1.23) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +Numbers can be automatically converted from the following Go types, pointers to these types, or any aliases of these types, such `type MyNumber int`: + +* `int`, `int8`, `int16`, `int32`, `int64` +* `uint`, `uint8`, `uint16`, `uint32`, `uint64` +* `float32`, `float64` +* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float) + +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. + +In this example, a `float64` is directly used to set a float64 attribute value: + +```go +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), 1.23) +``` + +In this example, a `types.List` of `types.Float64` is created from a `[]float64`: + +```go +listValue, diags := types.ListValueFrom(ctx, types.Float64Type, []float64{1.2, 2.4}) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/types/index.mdx b/website/docs/plugin/framework/handling-data/types/index.mdx new file mode 100644 index 000000000..735bed0b2 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/index.mdx @@ -0,0 +1,62 @@ +--- +page_title: 'Plugin Development - Framework: Types' +description: >- + Learn the types in the provider development framework. Attributes and blocks + in a resource, data source, or provider schema map to specific framework types. +--- + +# Types + +Types are value storage and access mechanism for resource, data source, or provider [schema](/terraform/plugin/framework/handling-data/schemas) data. Every attribute and block has an associated type, which describes the kind of data. These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as `*string`. Framework types can be extended by implementing [custom types](/terraform/plugin/framework/handling-data/types/custom) in provider code or shared libraries to provide specific use case functionality. + +## Available Types + +The framework type system supports the following types: + +- [Primitive](#primitive-types): Type that contains a single value, such as a boolean, number, or string. +- [Collection](#collection-types): Type that contains multiple values of a single element type, such as a list, map, or set. +- [Object](#object-type): Type that defines a mapping of explicit attribute names to value types. + +### Primitive Types + +Types that contain a single data value, such as a boolean, number, or string. These are directly associated with their [primitive attribute type](/terraform/plugin/framework/handling-data/attributes#primitive-attribute-types). + +| Type | Use Case | +|----------------|----------| +| [Bool](/terraform/plugin/framework/handling-data/types/bool) | Boolean true or false | +| [Float64](/terraform/plugin/framework/handling-data/types/float64) | 64-bit floating point number | +| [Int64](/terraform/plugin/framework/handling-data/types/int64) | 64-bit integer number | +| [Number](/terraform/plugin/framework/handling-data/types/number) | Arbitrary precision (generally over 64-bit, up to 512-bit) number | +| [String](/terraform/plugin/framework/handling-data/types/bool) | Collection of UTF-8 encoded characters | + +### Collection Types + +Types that contain multiple values of a single element type, such as a list, map, or set. + +These types are associated with: + +- [Collection attribute types](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types) +- Collection-based [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) (list, map, and set of [object type](#object-type)) +- Collection-based [nested block type](/terraform/plugin/framework/handling-data/blocks) (list and set of [object type](#object-type)) + +| Type | Use Case | +|----------------|----------| +| [List](/terraform/plugin/framework/handling-data/types/list) | Ordered collection of single element type | +| [Map](/terraform/plugin/framework/handling-data/types/map) | Mapping of arbitrary string keys to values of single element type | +| [Set](/terraform/plugin/framework/handling-data/types/set) | Unordered, unique collection of single element type | + +### Object Type + +Type that defines a mapping of explicit attribute names to value types. + +This type is associated with: + +- [Single nested attibute type](/terraform/plugin/framework/handling-data/attributes/single-nested) +- [Single nested block type](/terraform/plugin/framework/handling-data/blocks/single-nested) +- Nested object within collection-based [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) (list, map, and set of [object type](#object-type)) +- Nested object within collection-based [nested block type](/terraform/plugin/framework/handling-data/blocks) (list and set of [object type](#object-type)) +- [Object attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types) + +| Type | Use Case | +|----------------|----------| +| [Object](/terraform/plugin/framework/handling-data/types/object) | Mapping of explicit attribute names to values | diff --git a/website/docs/plugin/framework/handling-data/types/int64.mdx b/website/docs/plugin/framework/handling-data/types/int64.mdx new file mode 100644 index 000000000..daf46a796 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/int64.mdx @@ -0,0 +1,119 @@ +--- +page_title: 'Plugin Development - Framework: Int64 Type' +description: >- + Learn the int64 value type in the provider development framework. +--- + +# Int64 Type + + + +Use [Float64 Type](/terraform/plugin/framework/handling-data/types/int64) for 64-bit floating point numbers. Use [Number Attribute](/terraform/plugin/framework/handling-data/types/number) for arbitrary precision numbers. + + + +Int64 types store a 64-bit integer number. + +By default, int64 from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.Int64Type`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Type) and its associated value storage type of [`types.Int64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as `*int64`. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a int64 value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.Int64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#Int64Attribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.Int64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#Int64Attribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.Int64Attribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#Int64Attribute) | + +If the int64 value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElemType` field to `types.Int64Type` or the appropriate [custom type](#extending). + +If the int64 value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttrTypes` map value to `types.Int64Type` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/int64#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.Int64` in this case. + + + +Access `types.Int64` information via the following methods: + +* [`(types.Int64).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Int64Value.IsNull): Returns true if the int64 is null. +* [`(types.Int64).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Int64Value.IsUnknown): Returns true if the int64 is unknown. +* [`(types.Int64).ValueInt64() int64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Int64Value.ValueInt64): Returns the known int64, or `0` if null or unknown. +* [`(types.Int64).ValueInt64Pointer() *int64`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#Int64Value.ValueInt64Pointer): Returns a int64 pointer to a known value, `nil` if null, or a pointer to `0` if unknown. + +In this example, a int64 value is checked for being null or unknown value first, before accessing its known value: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.Int64 `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +// myInt64 now contains a Go int64 with the known value +myInt64 := data.ExampleAttribute.ValueInt64() +``` + +## Setting Values + +Call one of the following to create a `types.Int64` value: + +* [`types.Int64Null()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Null): A null int64 value. +* [`types.Int64Unknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Unknown): An unknown int64 value. +* [`types.Int64Value(int64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64Value): A known value. +* [`types.Int64PointerValue(*int64)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Int64PointerValue): A known value. + +In this example, a known int64 value is created: + +```go +types.Int64Value(123) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +Numbers can be automatically converted from the following Go types, pointers to these types, or any aliases of these types, such `type MyNumber int`: + +* `int`, `int8`, `int16`, `int32`, `int64` +* `uint`, `uint8`, `uint16`, `uint32`, `uint64` +* `float32`, `float64` +* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float) + +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. + +In this example, a `int64` is directly used to set a int64 attribute value: + +```go +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), 123) +``` + +In this example, a `types.List` of `types.Int64` is created from a `[]int64`: + +```go +listValue, diags := types.ListValueFrom(ctx, types.Int64Type, []int64{123, 456}) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/types/list.mdx b/website/docs/plugin/framework/handling-data/types/list.mdx new file mode 100644 index 000000000..42e98925e --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/list.mdx @@ -0,0 +1,121 @@ +--- +page_title: 'Plugin Development - Framework: List Type' +description: >- + Learn the list value type in the provider development framework. +--- + +# List Type + +List types store an ordered collection of single element type. + +By default, lists from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.ListType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListType) and its associated value storage type of [`types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#List). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as a slice. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a list of a single element type to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ListAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ListAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ListAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ListAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ListAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ListAttribute) | + +Use one of the following attribute types to directly add a list of a nested attributes to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute or Block Type | +|-------------|-------------------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ListNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ListNestedAttribute) | +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ListNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ListNestedBlock) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ListNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ListNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ListNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ListNestedBlock) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ListNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ListNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ListNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ListNestedBlock) | + +If the list value should be the element type of another [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field to `types.ListType{ElemType: /* ... */}` or the appropriate [custom type](#extending). + +If the list value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value to `types.ListType{ElemType: /* ... */}` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/list#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.List` in this case. + + + +Access `types.List` information via the following methods: + +* [`(types.List).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ListValue.IsNull): Returns `true` if the list is null. +* [`(types.List).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ListValue.IsUnknown): Returns `true` if the list is unknown. Returns `false` if the number of elements is known, any of which may be unknown. +* [`(types.List).Elements() []attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ListValue.Elements): Returns the known `[]attr.Value` value, or `nil` if null or unknown. +* [`(types.List).ElementsAs(context.Context, any, bool) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ListValue.ElementsAs): Converts the known values into the given Go type, if possible. It is recommended to use a slice of framework types to account for elements which may be unknown. + +In this example, a list of strings value is checked for being null or unknown value first, before accessing its known value elements as a `[]types.String`: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.List `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +elements := make([]types.String, 0, len(data.ExampleAttribute.Elements())) +diags := data.ExampleAttribute.ElementsAs(ctx, &elements, false) +``` + +## Setting Values + +Call one of the following to create a `types.List` value: + +* [`types.ListNull(attr.Type) types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListNull): A null list value with the given element type. +* [`types.ListUnknown(attr.Type) types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListUnknown): An unknown list value with the given element type. +* [`types.ListValue(attr.Type, []attr.Value) (types.List, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValue): A known value with the given element type and values. +* [`types.ListValueFrom(context.Context, attr.Type, any) (types.List, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom): A known value with the given element type and values. This can convert the source data from standard Go types into framework types as noted in the documentation for each element type, such as giving `[]*string` for a `types.List` of `types.String`. +* [`types.ListValueMust(map[string]attr.Type, map[string]attr.Value) types.List`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueMust): A known value with the given element type and values. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. + +In this example, a known list value is created from framework types: + +```go +elements := []attr.Value{types.StringValue("one"), types.StringValue("two")} +listValue, diags := types.ListValue(types.StringType, elements) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +A Go built-in slice type (`[]T`) or type alias of a slice type such as `type MyListType []T` can be used instead. + +In this example, a `[]string` is directly used to set a list attribute value: + +```go +elements := []string{"one", "two"} +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), elements) +``` + +In this example, a `types.List` of `types.String` is created from a `[]string`: + +```go +elements := []string{"one", "two"} +listValue, diags := types.ListValueFrom(ctx, types.StringType, elements) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/types/map.mdx b/website/docs/plugin/framework/handling-data/types/map.mdx new file mode 100644 index 000000000..96f3f0b78 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/map.mdx @@ -0,0 +1,127 @@ +--- +page_title: 'Plugin Development - Framework: Map Type' +description: >- + Learn the map value type in the provider development framework. +--- + +# Map Type + +Map types store an ordered collection of single element type. + +By default, maps from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.MapType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapType) and its associated value storage type of [`types.Map`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Map). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as a map. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a map of a single element type to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.MapAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#MapAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.MapAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#MapAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.MapAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#MapAttribute) | + +Use one of the following attribute types to directly add a map of a nested attributes to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.MapNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#MapNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.MapNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#MapNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.MapNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SetNestedAttribute) | + +If the map value should be the element type of another [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field to `types.MapType{ElemType: /* ... */}` or the appropriate [custom type](#extending). + +If the map value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value to `types.MapType{ElemType: /* ... */}` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/map#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.Map` in this case. + + + +Access `types.Map` information via the following methods: + +* [`(types.Map).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#MapValue.IsNull): Returns `true` if the map is null. +* [`(types.Map).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#MapValue.IsUnknown): Returns `true` if the map is unknown. Returns `false` if the number of elements is known, any of which may be unknown. +* [`(types.Map).Elements() map[string]attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#MapValue.Elements): Returns the known `map[string]attr.Value` value, or `nil` if null or unknown. +* [`(types.Map).ElementsAs(context.Context, any, bool) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#MapValue.ElementsAs): Converts the known values into the given Go type, if possible. It is recommended to use a map of framework types to account for elements which may be unknown. + +In this example, a map of strings value is checked for being null or unknown value first, before accessing its known value elements as a `map[string]types.String`: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.Map `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +elements := make(map[string]types.String, len(data.ExampleAttribute.Elements())) +diags := data.ExampleAttribute.ElementsAs(ctx, &elements, false) +``` + +## Setting Values + +Call one of the following to create a `types.Map` value: + +* [`types.MapNull(attr.Type) types.Map`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapNull): A null list value with the given element type. +* [`types.MapUnknown(attr.Type) types.Map`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapUnknown): An unknown list value with the given element type. +* [`types.MapValue(attr.Type, map[string]attr.Value) (types.Map, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValue): A known value with the given element type and values. +* [`types.MapValueFrom(context.Context, attr.Type, any) (types.Map, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom): A known value with the given element type and values. This can convert the source data from standard Go types into framework types as noted in the documentation for each element type, such as giving `map[string]*string` for a `types.Map` of `types.String`. +* [`types.MapValueMust(map[string]attr.Type, map[string]attr.Value) types.Map`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueMust): A known value with the given element type and values. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. + +In this example, a known map value is created from framework types: + +```go +elements := map[string]attr.Value{ + "key1": types.StringValue("value1"), + "key2": types.StringValue("value2"), +} +mapValue, diags := types.MapValue(types.StringType, elements) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +A Go built-in map of string key type (`map[string]T`) or type alias of a map of string key type such as `type MyMapType map[string]T` can be used instead. + +In this example, a `map[string]string` is directly used to set a map attribute value: + +```go +elements := map[string]string{ + "key1": "value1", + "key2": "value2", +} +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), elements) +``` + +In this example, a `types.Map` of `types.String` is created from a `map[string]string`: + +```go +elements := map[string]string{ + "key1": "value1", + "key2": "value2", +} +mapValue, diags := types.MapValueFrom(ctx, types.StringType, elements) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/types/number.mdx b/website/docs/plugin/framework/handling-data/types/number.mdx new file mode 100644 index 000000000..b8312efbd --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/number.mdx @@ -0,0 +1,115 @@ +--- +page_title: 'Plugin Development - Framework: Number Type' +description: >- + Learn the float64 value type in the provider development framework. +--- + +# Number Type + + + +Use [Float64 Type](/terraform/plugin/framework/handling-data/types/float64) for 64-bit floating point numbers. Use [Int64 Type](/terraform/plugin/framework/handling-data/types/int64) for 64-bit integer numbers. + + + +Number types store an arbitrary precision (generally more than 64-bit, up to 512-bit) number. + +By default, number from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.NumberType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberType) and its associated value storage type of [`types.Number`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Number). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as `*big.Float`. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a number value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.NumberAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#NumberAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.NumberAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#NumberAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.NumberAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#NumberAttribute) | + +If the number value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElemType` field to `types.NumberType` or the appropriate [custom type](#extending). + +If the number value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttrTypes` map value to `types.NumberType` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/number#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.Number` in this case. + + + +Access `types.Number` information via the following methods: + +* [`(types.Number).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#NumberValue.IsNull): Returns true if the number is null. +* [`(types.Number).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#NumberValue.IsUnknown): Returns true if the number is unknown. +* [`(types.Number).ValueBigFloat() *big.Float`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#NumberValue.ValueNumber): Returns the known number, or the equivalent of `0.0` if null or unknown. + +In this example, a number value is checked for being null or unknown value first, before accessing its known value: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.Number `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +// myNumber now contains a Go *big.Float with the known value +myNumber := data.ExampleAttribute.ValueBigFloat() +``` + +## Setting Values + +Call one of the following to create a `types.Number` value: + +* [`types.NumberNull()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberNull): A null float64 value. +* [`types.NumberUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberUnknown): An unknown float64 value. +* [`types.NumberValue(*big.Float)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#NumberValue): A known value. + +In this example, a known number value is created: + +```go +types.NumberValue(big.NewFloat(1.23)) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +Numbers can be automatically converted from the following Go types, pointers to these types, or any aliases of these types, such `type MyNumber int`: + +* `int`, `int8`, `int16`, `int32`, `int64` +* `uint`, `uint8`, `uint16`, `uint32`, `uint64` +* `float32`, `float64` +* [`*big.Int`](https://pkg.go.dev/math/big#Int), [`*big.Float`](https://pkg.go.dev/math/big#Float) + +In this example, a `*big.Float` is directly used to set a number attribute value: + +```go +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), big.NewFloat(1.23)) +``` + +In this example, a `types.List` of `types.Number` is created from a `[]*big.Float`: + +```go +listValue, diags := types.ListValueFrom(ctx, types.NumberType, []*big.Float{big.NewFloat(1.2), big.NewFloat(2.4)}) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/types/object.mdx b/website/docs/plugin/framework/handling-data/types/object.mdx new file mode 100644 index 000000000..5c02451a9 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/object.mdx @@ -0,0 +1,170 @@ +--- +page_title: 'Plugin Development - Framework: Object Type' +description: >- + Learn the object value type in the provider development framework. +--- + +# Object Type + +Object types store a mapping of explicit attribute names to value types. Objects must declare all attribute values, even when null or unknown, unless the entire object is null or unknown. + +By default, objects from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.ObjectType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectType) and its associated value storage type of [`types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Object). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as a struct. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + + + +Use [nested attribute types](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types) instead of object attribute types where possible. Object attributes have limited utility as they can only define type information. + + + +Use one of the following attribute types to directly add a single structure of a nested attributes to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute or Block Type | +|-------------|-------------------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SingleNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SingleNestedAttribute) | +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SingleNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SingleNestedBlock) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SingleNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SingleNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SingleNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SingleNestedBlock) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SingleNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SingleNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SingleNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SingleNestedBlock) | + +If a wrapping collection is needed on the structure of nested attributes, any of the other nested attribute and nested block types can be used. + +Use one of the following attribute types to directly add an object value directly to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.ObjectAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#ObjectAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.ObjectAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#ObjectAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.ObjectAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#ObjectAttribute) | + +If the object value should be the element type of another [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field to `types.ObjectType{AttrTypes: /* ... */}` or the appropriate [custom type](#extending). + +If the object value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value to `types.ObjectType{AttrTypes: /* ... */}` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the associated [attribute documentation](/terraform/plugin/framework/handling-data/attributes) to understand how schema-based data gets mapped into accessible values, such as a `types.Object` in this case. + + + +Access `types.Object` information via the following methods: + +* [`(types.Object).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ObjectValue.IsNull): Returns `true` if the object is null. +* [`(types.Object).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ObjectValue.IsUnknown): Returns `true` if the object is unknown. +* [`(types.Object).Attributes() map[string]attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ObjectValue.Attributes): Returns the known `map[string]attr.Value` value, or `nil` if null or unknown. +* [`(types.Object).As(context.Context, any, ObjectAsOptions) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#ObjectValue.As): Converts the known values into the given Go type, if possible. It is recommended to use a struct of framework types to account for attributes which may be unknown. + +In this example, an object with a string attribute is checked for being null or unknown value first, before accessing its known value attributes as a Go struct type: + +```go +// Example data model definitions +// type ExampleModel struct { +// ExampleAttribute types.Object `tfsdk:"example_attribute"` +// } +// +// type ExampleAttributeModel struct { +// StringAttribute types.String `tfsdk:"string_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +var exampleAttribute ExampleAttributeModel + +diags := data.ExampleAttribute.As(ctx, &exampleAttribute, basetypes.ObjectAsOptions{}) +// Object data now is accessible, such as: exampleAttribute.StringAttribute.StringValue() +``` + +## Setting Values + +Call one of the following to create a `types.Object` value: + +* [`types.ObjectNull(map[string]attr.Type) types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectNull): A null object value with the given element type. +* [`types.ObjectUnknown(map[string]attr.Type) types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectUnknown): An unknown object value with the given element type. +* [`types.ObjectValue(map[string]attr.Type, map[string]attr.Value) (types.Object, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValue): A known value with the given attribute type mapping and attribute values mapping. +* [`types.ObjectValueFrom(context.Context, map[string]attr.Type, any) (types.Object, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom): A known value with the given attribute type mapping and values. This can convert the source data from standard Go types into framework types as noted in the documentation for each type, such as giving a `struct` for a `types.Object`. +* [`types.ObjectValueMust(map[string]attr.Type, map[string]attr.Value) types.Object`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueMust): A known value with the given attribute type mapping and attribute value mapping. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. + +In this example, a known object value is created from framework types: + +```go +elementTypes := map[string]attr.Type{ + "attr1": types.StringType, + "attr2": types.Int64Type, +} +elements := map[string]attr.Value{ + "attr1": types.StringValue("value"), + "attr2": types.Int64Value(123), +} +objectValue, diags := types.ObjectValue(elementTypes, elements) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +Objects can be automatically converted to any Go struct type that follows these constraints to prevent accidental data loss: + +* Every struct type must be an acceptable conversion type according to the type documentation, such as `*string` being acceptable for a string type. However, it is recommended to use framework types to simplify data modeling (one model type for accessing and setting data) and prevent errors when encountering unknown values from Terraform. +* Every struct field must have a `tfsdk` struct tag and every attribute in the object must have a corresponding struct tag. The `tfsdk` struct tag must name an attribute in the object that it is being mapped or be set to `-` to explicitly declare it does not map to an attribute in the object. + +In this example, a struct is directly used to set an object attribute value: + +```go +type ExampleAttributeModel struct { + Int64Attribute types.Int64 `tfsdk:"int64_attribute` + StringAttribute types.String `tfsdk:"string_attribute"` +} + +value := ExampleAttributeModel{ + Int64Attribute: types.Int64Value(123), + StringAttribute: types.StringValue("example"), +} + +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), value) +``` + +In this example, a `types.Object` is created from a struct: + +```go +type ExampleAttributeModel struct { + Int64Attribute types.Int64 `tfsdk:"int64_attribute` + StringAttribute types.String `tfsdk:"string_attribute"` +} + +func (m ExampleAttributeModel) AttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "int64_attribute": types.Int64Type, + "string_attribute": types.StringType, + } +} + +value := ExampleAttributeModel{ + Int64Attribute: types.Int64Value(123), + StringAttribute: types.StringValue("example"), +} + +objectValue, diags := types.ObjectValueFrom(ctx, value.AttributeTypes(), value) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/types/set.mdx b/website/docs/plugin/framework/handling-data/types/set.mdx new file mode 100644 index 000000000..72c85bc82 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/set.mdx @@ -0,0 +1,121 @@ +--- +page_title: 'Plugin Development - Framework: Set Type' +description: >- + Learn the set value type in the provider development framework. +--- + +# Set Type + +Set types store an ordered collection of single element type. + +By default, sets from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.SetType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetType) and its associated value storage type of [`types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#Set). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as a slice. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a set of a single element type to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SetAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SetAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SetAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SetAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SetAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SetAttribute) | + +Use one of the following attribute types to directly add a set of a nested attributes to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute or Block Type | +|-------------|-------------------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SetNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SetNestedAttribute) | +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.SetNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#SetNestedBlock) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SetNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SetNestedAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.SetNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#SetNestedBlock) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SetNestedAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SetNestedAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.SetNestedBlock`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#SetNestedBlock) | + +If the set value should be the element type of another [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElementType` field to `types.SetType{ElemType: /* ... */}` or the appropriate [custom type](#extending). + +If the set value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttributeTypes` map value to `types.SetType{ElemType: /* ... */}` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/set#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.Set` in this case. + + + +Access `types.Set` information via the following methods: + +* [`(types.Set).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#SetValue.IsNull): Returns `true` if the set is null. +* [`(types.Set).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#SetValue.IsUnknown): Returns `true` if the set is unknown. Returns `false` if the number of elements is known, any of which may be unknown. +* [`(types.Set).Elements() []attr.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#SetValue.Elements): Returns the known `[]attr.Value` value, or `nil` if null or unknown. +* [`(types.Set).ElementsAs(context.Context, any, bool) diag.Diagnostics`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#SetValue.ElementsAs): Converts the known values into the given Go type, if possible. It is recommended to use a slice of framework types to account for elements which may be unknown. + +In this example, a set of strings value is checked for being null or unknown value first, before accessing its known value elements as a `[]types.String`: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.Set `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +elements := make([]types.String, 0, len(data.ExampleAttribute.Elements())) +diags := data.ExampleAttribute.ElementsAs(ctx, &elements, false) +``` + +## Setting Values + +Call one of the following to create a `types.Set` value: + +* [`types.SetNull(attr.Type) types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetNull): A null set value with the given element type. +* [`types.SetUnknown(attr.Type) types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetUnknown): An unknown set value with the given element type. +* [`types.SetValue(attr.Type, []attr.Value) (types.Set, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValue): A known value with the given element type and values. +* [`types.SetValueFrom(context.Context, attr.Type, any) (types.Set, diag.Diagnostics)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom): A known value with the given element type and values. This can convert the source data from standard Go types into framework types as noted in the documentation for each element type, such as giving `[]*string` for a `types.Set` of `types.String`. +* [`types.SetValueMust(map[string]attr.Type, map[string]attr.Value) types.Set`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueMust): A known value with the given element type and values. Any diagnostics are converted to a runtime panic. This is recommended only for testing or exhaustively tested logic. + +In this example, a known set value is created from framework types: + +```go +elements := []attr.Value{types.StringValue("one"), types.StringValue("two")} +setValue, diags := types.SetValue(types.StringType, elements) +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +A Go built-in slice type (`[]T`) or type alias of a slice type such as `type MyListType []T` can be used instead. + +In this example, a `[]string` is directly used to set a set attribute value: + +```go +elements := []string{"one", "two"} +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), elements) +``` + +In this example, a `types.Set` of `types.String` is created from a `[]string`: + +```go +elements := []string{"one", "two"} +setValue, diags := types.SetValueFrom(ctx, types.StringType, elements) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. diff --git a/website/docs/plugin/framework/handling-data/types/string.mdx b/website/docs/plugin/framework/handling-data/types/string.mdx new file mode 100644 index 000000000..0284d5497 --- /dev/null +++ b/website/docs/plugin/framework/handling-data/types/string.mdx @@ -0,0 +1,120 @@ +--- +page_title: 'Plugin Development - Framework: String Type' +description: >- + Learn the string value type in the provider development framework. +--- + +# String Type + +String types store a collection of UTF-8 encoded bytes. + +By default, strings from [schema](/terraform/plugin/framework/handling-data/schemas) (configuration, plan, and state) data are represented in the framework by [`types.StringType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringType) and its associated value storage type of [`types.String`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#String). These types fully support Terraform's [type system concepts](/terraform/plugin/framework/handling-data/terraform-concepts) that cannot be represented in Go built-in types, such as `*string`. Framework types can be [extended](#extending) by provider code or shared libraries to provide specific use case functionality. + +## Schema Definitions + +Use one of the following attribute types to directly add a string value to a [schema](/terraform/plugin/framework/handling-data/schemas) or [nested attribute type](/terraform/plugin/framework/handling-data/attributes#nested-attribute-types): + +| Schema Type | Attribute Type | +|-------------|----------------| +| [Data Source](/terraform/plugin/framework/data-sources) | [`schema.StringAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#StringAttribute) | +| [Provider](/terraform/plugin/framework/provider) | [`schema.StringAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#StringAttribute) | +| [Resource](/terraform/plugin/framework/resources) | [`schema.StringAttribute`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#StringAttribute) | + +If the string value should be the element type of a [collection attribute type](/terraform/plugin/framework/handling-data/attributes#collection-attribute-types), set the `ElemType` field to `types.StringType` or the appropriate [custom type](#extending). + +If the string value should be a value type of an [object attribute type](/terraform/plugin/framework/handling-data/attributes#object-attribute-type), set the `AttrTypes` map value to `types.StringType` or the appropriate [custom type](#extending). + +## Accessing Values + + + +Review the [attribute documentation](/terraform/plugin/framework/handling-data/attributes/string#accessing-values) to understand how schema-based data gets mapped into accessible values, such as a `types.String` in this case. + + + + + +The `(types.String).String()` method is reserved for debugging purposes and returns `""` if the value is null and `""` if the value is unknown. Use `(types.String).ValueString()` or `(types.String).ValueStringPointer()` for accessing a known string value. + + + +Access `types.String` information via the following methods: + +* [`(types.String).IsNull() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#StringValue.IsNull): Returns true if the string is null. +* [`(types.String).IsUnknown() bool`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#StringValue.IsUnknown): Returns true if the string is unknown. +* [`(types.String).ValueString() string`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#StringValue.ValueString): Returns the known string, or an empty string if null or unknown. +* [`(types.String).ValueStringPointer() *string`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types/basetypes#StringValue.ValueStringPointer): Returns a string pointer to a known value, `nil` if null, or a pointer to an empty string if unknown. + +In this example, a string value is checked for being null or unknown value first, before accessing its known value: + +```go +// Example data model definition +// type ExampleModel struct { +// ExampleAttribute types.String `tfsdk:"example_attribute"` +// } +// +// This would be filled in, such as calling: req.Plan.Get(ctx, &data) +var data ExampleModel + +// optional logic for handling null value +if data.ExampleAttribute.IsNull() { + // ... +} + +// optional logic for handling unknown value +if data.ExampleAttribute.IsUnknown() { + // ... +} + +// myString now contains a Go string with the known value +myString := data.ExampleAttribute.ValueString() +``` + +## Setting Values + +Call one of the following to create a `types.String` value: + +* [`types.StringNull()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringNull): A null string value. +* [`types.StringUnknown()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringUnknown): An unknown string value. +* [`types.StringValue(string)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringValue): A known value. +* [`types.StringPointerValue(*string)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#StringPointerValue): A known value. + +In this example, a known string value is created: + +```go +types.StringValue("example value") +``` + +Otherwise, for certain framework functionality that does not require `types` implementations directly, such as: + +* [`(tfsdk.State).SetAttribute()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#State.SetAttribute) +* [`types.ListValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ListValueFrom) +* [`types.MapValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#MapValueFrom) +* [`types.ObjectValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#ObjectValueFrom) +* [`types.SetValueFrom()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/types#SetValueFrom) + +A Go built-in `string`, `*string` (only with typed `nil`, `(*string)(nil)`), or type alias of `string` such as `type MyStringType string` can be used instead. + +In this example, a `string` is directly used to set a string attribute value: + +```go +diags := resp.State.SetAttribute(ctx, path.Root("example_attribute"), "example value") +``` + +In this example, a `types.List` of `types.String` is created from a `[]string`: + +```go +listValue, diags := types.ListValueFrom(ctx, types.StringType, []string{"value one", "value two"}) +``` + +## Extending + +The framework supports extending its base type implementations with [custom types](/terraform/plugin/framework/handling-data/types/custom). These can adjust expected provider code usage depending on their implementation. + +### Common Use Case Types + +HashiCorp provides additional Go modules which contain custom string type implementations covering common use cases with validation and semantic equality logic: + +* [`terraform-plugin-framework-jsontypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-jsontypes): JSON encoded strings, such as exact byte strings and normalized strings +* [`terraform-plugin-framework-nettypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-nettypes): Networking strings, such as IPv4 addresses, IPv6 addresses, and CIDRs +* [`terraform-plugin-framework-timetypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework-timetypes): Timestamp strings, such as RFC3339 diff --git a/website/docs/plugin/framework/handling-data/writing-state.mdx b/website/docs/plugin/framework/handling-data/writing-state.mdx index 04bf0c708..6636fbcb5 100644 --- a/website/docs/plugin/framework/handling-data/writing-state.mdx +++ b/website/docs/plugin/framework/handling-data/writing-state.mdx @@ -59,7 +59,7 @@ func (r ThingResource) Create(ctx context.Context, ``` The state information is represented as an object, and gets persisted like an -object. Refer to the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#converting-from-go-types-to-framework-types) for an explanation on how +object. Refer to the [object type](/terraform/plugin/framework/handling-data/types/object) documentation for an explanation on how objects get persisted and what Go types are valid for persisting as an object. ## Set a Single Attribute or Block Value @@ -82,5 +82,4 @@ func (r ThingResource) Read(ctx context.Context, } ``` -Refer to the [conversion rules](/terraform/plugin/framework/handling-data/conversion-rules#converting-from-go-types-to-framework-types) -for more information about supported Go types. \ No newline at end of file +Refer to the [types](/terraform/plugin/framework/handling-data/types) documentation for more information about supported Go types. diff --git a/website/docs/plugin/framework/migrating/attributes-blocks/fields.mdx b/website/docs/plugin/framework/migrating/attributes-blocks/fields.mdx index 22807d1f0..8a594ca86 100644 --- a/website/docs/plugin/framework/migrating/attributes-blocks/fields.mdx +++ b/website/docs/plugin/framework/migrating/attributes-blocks/fields.mdx @@ -19,8 +19,8 @@ The following table describes the mapping between [SDK Schema Fields](https://pk | Optional | `Optional` field on attribute | | Computed | `Computed` field on attribute | | ForceNew | [RequiresReplace](/terraform/plugin/framework/migrating/attributes-blocks/force-new) on `PlanModifiers` field on attribute or implementation of [ResourceWithModifyPlan](/terraform/plugin/framework/migrating/resources/plan-modification#framework) interface | -| DiffSuppressFunc | [Custom Types](/terraform/plugin/framework/handling-data/custom-types), [PlanModifiers](/terraform/plugin/framework/migrating/resources/plan-modification#framework) field on attribute, or implementation of [ResourceWithModifyPlan](/terraform/plugin/framework/migrating/resources/plan-modification#framework) interface | -| DiffSuppressOnRefresh | [Custom Types](/terraform/plugin/framework/handling-data/custom-types) semantic equality logic or manual logic in [Read](/terraform/plugin/framework/migrating/resources/crud) method on resource | +| DiffSuppressFunc | [Custom Types](/terraform/plugin/framework/handling-data/types/custom), [PlanModifiers](/terraform/plugin/framework/migrating/resources/plan-modification#framework) field on attribute, or implementation of [ResourceWithModifyPlan](/terraform/plugin/framework/migrating/resources/plan-modification#framework) interface | +| DiffSuppressOnRefresh | [Custom Types](/terraform/plugin/framework/handling-data/types/custom) semantic equality logic or manual logic in [Read](/terraform/plugin/framework/migrating/resources/crud) method on resource | | Default | `Default` field on attribute using one of the predefined [Defaults](/terraform/plugin/framework/resources/default#common-use-case-attribute-defaults) or implementing one of the [`schema` package](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/defaults) interfaces | | DefaultFunc | `Default` field on attribute using one of the predefined [Defaults](/terraform/plugin/framework/resources/default#common-use-case-attribute-defaults) or implementing one of the [`schema` package](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema/defaults) interfaces | | Description | `Description` field on attribute | @@ -36,8 +36,8 @@ The following table describes the mapping between [SDK Schema Fields](https://pk | AtLeastOneOf | [Predefined Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-predefined) | | RequiredWith | [Predefined Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-predefined) | | Deprecated | `DeprecationMessage` field on attribute | -| ValidateFunc | [Predefined Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-predefined), [Custom Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-custom), or [Custom Types](/terraform/plugin/framework/handling-data/custom-types) validation logic | -| ValidateDiagFunc | [Predefined Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-predefined), [Custom Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-custom), or [Custom Types](/terraform/plugin/framework/handling-data/custom-types) validation logic | +| ValidateFunc | [Predefined Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-predefined), [Custom Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-custom), or [Custom Types](/terraform/plugin/framework/handling-data/types/custom) validation logic | +| ValidateDiagFunc | [Predefined Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-predefined), [Custom Validators](/terraform/plugin/framework/migrating/attributes-blocks/validators-custom), or [Custom Types](/terraform/plugin/framework/handling-data/types/custom) validation logic | | Sensitive | `Sensitive` field on attribute |