Skip to content

Commit 221ae8f

Browse files
authored
Improvements to Documentation (#584)
* Cleaning up docs (#583) * Consolidating attribute documentation in the attributes page (#583)
1 parent 26244b8 commit 221ae8f

File tree

7 files changed

+475
-821
lines changed

7 files changed

+475
-821
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@
152152
{
153153
"title": "Conversion Rules",
154154
"path": "handling-data/conversion-rules"
155+
},
156+
{
157+
"title": "Custom Types",
158+
"path": "handling-data/custom-types"
155159
}
156160
]
157161
},

website/docs/plugin/framework/getting-started/code-walkthrough.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,9 @@ Refer to [Data Sources](/plugin/framework/data-sources) for more details and con
353353

354354
## Terraform Configuration
355355

356-
With the definitions we have for [provider server](#provider-server), [provider](#provider), [resource](#resource) and [data source](#data-source), we can run the provider by specifying configuration and executing `terraform apply`.
356+
Refer to [terraform-provider-scaffolding-framework](https://github.com/hashicorp/terraform-provider-scaffolding-framework) for details on how to wire together a [provider server](#provider-server), [provider](#provider), [resource](#resource) and [data source](#data-source).
357+
358+
Once wired together, run the provider by specifying configuration and executing `terraform apply`.
357359

358360
### Resource Configuration
359361

website/docs/plugin/framework/handling-data/attributes.mdx

Lines changed: 157 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -405,56 +405,175 @@ Call one of the following to create a `types.Set`:
405405
* [`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](/plugin/framework/accessing-values#conversion-rules).
406406
* [`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.
407407

408-
## Create Provider-Defined Types and Values
408+
### Nested Attributes
409409

410-
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.
410+
-> Only supported when using protocol version 6.
411411

412-
~> **Important:** Specifying plan customization for attribute types is not yet
413-
supported, limiting their utility. Support is expected in the near future.
412+
[Nested attributes](/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](/language/expressions).
414413

415-
### `attr.Type` Interface
414+
#### SingleNestedAttribute
416415

417-
Use the [`attr.Type`
418-
interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/attr#Type)
419-
to implement an attribute type. It tells Terraform about its constraints and tells the framework how to create new attribute values from the information Terraform supplies. `attr.Type` has the following methods.
416+
With single nested attributes, the attribute behaves like an object. The practitioner can only specify one definition of the nested attributes.
420417

421-
| Method | Description |
422-
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
423-
| `TerraformType` | Returns the [`tftypes.Type` value](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#Type) that describes its type constraints. This is how Terraform will know what type of values it can accept. |
424-
| `ValueFromTerraform` | Returns an attribute value from the [`tftypes.Value`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#Value) that Terraform supplies, or to return an error if it cannot. This error should not be used for validation purposes, and is expected to indicate programmer error, not practitioner error. |
425-
| `Equal` | Returns true if the attribute type is considered equal to the passed attribute type. |
418+
```tf
419+
resource "example_foo" "bar" {
420+
nested_attribute = {
421+
hello = "world"
422+
demo = true
423+
}
424+
}
425+
```
426426

427-
### `AttributePathStepper` Interface
427+
```go
428+
func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
429+
resp.Schema = schema.Schema{
430+
Attributes: map[string]schema.Attribute{
431+
"nested_attribute": schema.SingleNestedAttribute{
432+
/* ... */
433+
Attributes: map[string]schema.Attribute{
434+
"hello": schema.StringAttribute{
435+
/* ... */
436+
},
437+
"demo": schema.BoolAttribute{
438+
/* ... */
439+
},
440+
},
441+
},
442+
},
443+
}
444+
}
445+
```
428446

429-
All attribute types must implement the [`tftypes.AttributePathStepper`
430-
interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#AttributePathStepper),
431-
so the framework can access element or attribute types using attribute paths.
447+
#### ListNestedAttribute
432448

433-
### `xattr.TypeWithValidation` Interface
449+
With list nested attributes, the attribute behaves like a list of objects. The practitioner can
450+
specify any number of groups of these attributes.
434451

435-
If validation for type values is desired, use the [`xattr.TypeWithValidation` interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/attr/xattr#TypeWithValidation) to include validation logic for type values. The framework will call this functionality when validating all values based on the schema.
452+
```tf
453+
resource "example_foo" "bar" {
454+
nested_attribute = [
455+
{
456+
hello = "world"
457+
demo = true
458+
},
459+
{
460+
hello = "moon"
461+
demo = false
462+
},
463+
]
464+
}
465+
```
436466

437-
| Method | Description |
438-
| ---------- | ------------------------------------------------------------- |
439-
| `Validate` | Returns any warning or error diagnostics for the given value. |
467+
```go
468+
func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
469+
resp.Schema = schema.Schema{
470+
Attributes: map[string]schema.Attribute{
471+
"nested_attribute": schema.ListNestedAttribute{
472+
/* ... */
473+
NestedObject: schema.NestedAttributeObject{
474+
Attributes: map[string]schema.Attribute{
475+
"hello": schema.StringAttribute{
476+
/* ... */
477+
},
478+
"demo": schema.BoolAttribute{
479+
/* ... */
480+
},
481+
},
482+
},
483+
},
484+
},
485+
}
486+
}
487+
```
440488

441-
### Type-Specific Interfaces
489+
#### MapNestedAttribute
442490

443-
| Case | Interface | Description |
444-
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
445-
| Elements of the same type | [`TypeWithElementType`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/attr#TypeWithElementType) | Attribute types that contain elements of the same type, like maps and lists, are required to implement `attr.TypeWithElementType`, which adds `WithElementType` and `ElementType` methods to the `attr.Type` interface. `WithElementType` must return a copy of the attribute type, but with its element type set to the passed type. `ElementType` must return the attribute type's element type. |
446-
| Elements of different types | [`TypeWithElementTypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/attr#TypeWithElementType) | Attribute types that contain elements of differing types, like tuples, are required to implement the `attr.TypeWithElementTypes`, which adds `WithElementTypes` and `ElementTypes` methods to the `attr.Type` interface. `WithElementTypes` must return a copy of the attribute type, but with its element types set to the passed element types. `ElementTypes` must return the attribute type's element types. |
447-
| Contain attributes | [`TypeWithAttributeTypes`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/attr#TypeWithAttributeTypes) | Attribute types that contain attributes, like objects, are required to implement the `attr.TypeWithAttributeTypes` interface, which adds `WithAttributeTypes` and `AttributeTypes` methods to the `attr.Type` interface. `WithAttributeTypes` must return a copy of the attribute type, but with its attribute types set to the passed attribute types. `AttributeTypes` must return the attribute type's attribute types. |
491+
With map nested attributes, the attribute behaves like a map of objects. The practitioner can
492+
specify any number of groups of these attributes, with string keys associated
493+
with each group.
448494

449-
### `attr.Value` Interface
495+
```tf
496+
resource "example_foo" "bar" {
497+
nested_attribute = {
498+
"red" = {
499+
hello = "world"
500+
demo = true
501+
},
502+
"blue" = {
503+
hello = "moon"
504+
demo = false
505+
},
506+
}
507+
}
508+
```
509+
510+
```go
511+
func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
512+
resp.Schema = schema.Schema{
513+
Attributes: map[string]schema.Attribute{
514+
"nested_attribute": schema.MapNestedAttribute{
515+
/* ... */
516+
NestedObject: schema.NestedAttributeObject{
517+
Attributes: map[string]schema.Attribute{
518+
"hello": schema.StringAttribute{
519+
/* ... */
520+
},
521+
"demo": schema.BoolAttribute{
522+
/* ... */
523+
},
524+
},
525+
},
526+
},
527+
},
528+
}
529+
}
530+
```
531+
532+
#### SetNestedAttribute
533+
534+
With set nested attributes, the attributes behave like a set of objects. The practitioner can
535+
specify any number of groups of these attributes.
536+
537+
```tf
538+
resource "example_foo" "bar" {
539+
nested_attribute = [
540+
{
541+
hello = "world"
542+
demo = true
543+
},
544+
{
545+
hello = "moon"
546+
demo = false
547+
},
548+
]
549+
}
550+
```
551+
552+
```go
553+
func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
554+
resp.Schema = schema.Schema{
555+
Attributes: map[string]schema.Attribute{
556+
"nested_attribute": schema.SetNestedAttribute{
557+
Optional: true,
558+
NestedObject: schema.NestedAttributeObject{
559+
Attributes: map[string]schema.Attribute{
560+
"hello": schema.StringAttribute{
561+
/* ... */
562+
},
563+
"demo": schema.BoolAttribute{
564+
/* ... */
565+
},
566+
},
567+
},
568+
},
569+
},
570+
}
571+
}
572+
```
573+
574+
## Create Provider-Defined Types and Values
575+
576+
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.
450577

451-
Use the [`attr.Value`
452-
interface](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/attr#Value)
453-
to implement an attribute value. It tells the framework how to express that
454-
attribute value in a way that Terraform will understand. `attr.Value` has the
455-
following methods.
578+
Refer to [Custom Types](plugin/framework/handling-data/custom-types) for further details on creating provider-defined types and values.
456579

457-
| Method | Description |
458-
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
459-
| `ToTerraformValue` | Returns a Go type that is valid input for [`tftypes.NewValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-go/tftypes#NewValue) for the `tftypes.Type` specified by the `attr.Type` that creates the `attr.Value`. |
460-
| `Equal` | Returns true if the passed attribute value should be considered to the attribute value the method is being called on. The passed attribute value is not guaranteed to be of the same Go type. |

website/docs/plugin/framework/handling-data/blocks.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ description: >-
88

99
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.
1010

11-
-> Use [nested attributes](/plugin/framework/handling-data/terraform-concepts#nested-attributes) for new schema implementations. Block support is mainly for migrating prior SDK-based providers.
11+
-> Use [nested attributes](/plugin/framework/handling-data/attributes#nested-attributes) for new schema implementations. Block support is mainly for migrating prior SDK-based providers.
1212

1313
In this example, the Terraform-defined `resource` block contains a provider-defined `ami` attribute and `network_interface` block.
1414

0 commit comments

Comments
 (0)