Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding docs for migrating from SDKv2 to the Framework #461

Merged
merged 30 commits into from Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fe9d1f2
Adding docs for migrating from SDKv2 to the Framework (#459)
bendbennett Aug 25, 2022
7e6158f
Apply suggestions from code review
bendbennett Aug 26, 2022
45718ce
Further fixes following review (#459)
bendbennett Aug 26, 2022
92724f4
Apply suggestions from code review
bendbennett Aug 30, 2022
2cf4cf6
Linting (#459)
bendbennett Aug 30, 2022
3fe19bc
Using /* ... */ to indicate code has been truncated and removing stat…
bendbennett Aug 30, 2022
77793a8
Removing text and link as nothing to link to at present (#459)
bendbennett Aug 30, 2022
0b5c8c3
Adding an example of migrating schema.TypeList to types.ListType (#459)
bendbennett Aug 30, 2022
0b9f120
Adding example of migrating from schema.ImportStatePassthroughContext…
bendbennett Aug 30, 2022
e0eb531
Removing extra blank line (#459)
bendbennett Aug 30, 2022
f5c4be6
Reword to clarify reference to practitioner-configurable blocks (#459)
bendbennett Sep 1, 2022
0e3d07b
Replacing ellipsis with in-line comment (#459)
bendbennett Sep 1, 2022
d781d32
Adding example of schema for using nested attributes when migrating c…
bendbennett Sep 1, 2022
d654477
Adding schema examples for common type migrations (#459)
bendbennett Sep 1, 2022
9314e01
Apply suggestions from code review
bendbennett Sep 1, 2022
474c8bb
Updating links to tagged version of random provider (#459)
bendbennett Sep 1, 2022
653c65c
Updating layout for data sources and providers (#459)
bendbennett Sep 1, 2022
a86abfb
Removing ellipsis and replacing with comment (#459)
bendbennett Sep 1, 2022
84fd690
Formatting code examples (#459)
bendbennett Sep 1, 2022
017d416
Updating computed-blocks example to use ListNestedAttributes (#459)
bendbennett Sep 2, 2022
1ae0d44
Restructuring resources and updating state upgrade example (#459)
bendbennett Sep 6, 2022
1afd243
Formatting headers (#459)
bendbennett Sep 7, 2022
7a07a06
Apply suggestions from code review
bendbennett Sep 7, 2022
3566d84
Merge branch 'bendbennett/issues-459' of github.com:hashicorp/terrafo…
bendbennett Sep 7, 2022
be4cb9e
Restructuring top-level Schemas page, adding example for config heade…
bendbennett Sep 7, 2022
64b35fc
Apply suggestions from code review
bendbennett Sep 8, 2022
f07b3e2
Replacing link using "Provider Schema" with "Providers" (#459)
bendbennett Sep 8, 2022
d14ee0d
Fixing formatting and wording (#459)
bendbennett Sep 8, 2022
73879d7
Fixing formatting and wording (#459)
bendbennett Sep 8, 2022
62e9ec0
Merge branch 'main' into bendbennett/issues-459
bendbennett Sep 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
91 changes: 91 additions & 0 deletions website/data/plugin-framework-nav-data.json
Expand Up @@ -79,5 +79,96 @@
{
"title": "Debugging",
"path": "debugging"
},
{
"title": "Migrating from SDK",
"routes": [
{
"title": "Overview",
"path": "migrating"
},
{
"title": "Testing",
"path": "migrating/testing"
},
{
"title": "Schema",
"path": "migrating/schema"
},
{
"title": "Provider",
"path": "migrating/provider"
},
{
"title": "Resources",
"routes": [
{
"title": "Schema",
"path": "migrating/resources/schema"
},
{
"title": "CRUD Functions",
"path": "migrating/resources/crud"
},
{
"title": "Import",
"path": "migrating/resources/import"
},
{
"title": "Plan Modification",
"path": "migrating/resources/plan-modification"
},
{
"title": "State Upgraders",
"path": "migrating/resources/state-upgrade"
}
]
},
{
"title": "Data Sources",
"path": "migrating/data-sources"
},
{
"title": "Attributes & Blocks",
"routes": [
{
"title": "Attribute Schema",
"path": "migrating/attributes-blocks/attribute-schema"
},
{
"title": "Attribute Types",
"path": "migrating/attributes-blocks/types"
},
{
"title": "Attribute Fields",
"path": "migrating/attributes-blocks/fields"
},
{
"title": "Default Values",
"path": "migrating/attributes-blocks/default-values"
},
{
"title": "Force New",
"path": "migrating/attributes-blocks/force-new"
},
{
"title": "Validators - Predefined",
"path": "migrating/attributes-blocks/validators-predefined"
},
{
"title": "Validators - Custom",
"path": "migrating/attributes-blocks/validators-custom"
},
{
"title": "Blocks",
"path": "migrating/attributes-blocks/blocks"
},
{
"title": "Blocks with Computed Fields",
"path": "migrating/attributes-blocks/blocks-computed"
}
]
}
Comment on lines +153 to +193
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have a Schema section, should these pages be moved under there as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense given that each of these pages relates to how the schema is set-up.

@laurapacilio @robin-norwood are you happy if I go ahead and move these pages as @bflad suggests?

]
}
]
@@ -0,0 +1,126 @@
---
page_title: 'Attribute Schema: Migrating from SDKv2 to the Framework'
description: >-
Migrate attributes from SDKv2 to the plugin Framework
---

# Attribute Schema

Attributes define how users can configure values for your Terraform provider, resources, and data sources. Refer to
[Schemas - Attributes](/plugin/framework/schemas#attributes) in the Framework documentation for details.

This page explains how to migrate an attribute from SDKv2 to the plugin Framework.

## SDKv2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you get a chance, you can try running markdownlint CLI against these files to catch things like this:

Suggested change
## SDKv2
## SDKv2

And further down with additional newlines after code fences. 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have installed and run markdownlint --disable MD013 -- ./website/docs/plugin/framework/migrating/*.

I'm ignoring the MD013/line-length Line length notifications.

In terms of the remaining notifications, I'm interested to hear feedback from @robin-norwood and @laurapacilio as I thought this was intentional but happy to fix however suits:

markdownlint --disable MD013 -- ./website/docs/plugin/framework/migrating/*
./website/docs/plugin/framework/migrating/data-sources.mdx:107 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### SDKv2"]
./website/docs/plugin/framework/migrating/data-sources.mdx:140 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Framework"]
./website/docs/plugin/framework/migrating/provider.mdx:111 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### SDKv2"]
./website/docs/plugin/framework/migrating/provider.mdx:138 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Framework"]
./website/docs/plugin/framework/migrating/provider.mdx:208 MD036/no-emphasis-as-heading/no-emphasis-as-header Emphasis used instead of a heading [Context: "SDKv2"]
./website/docs/plugin/framework/migrating/provider.mdx:233 MD036/no-emphasis-as-heading/no-emphasis-as-header Emphasis used instead of a heading [Context: "Framework"]
./website/docs/plugin/framework/migrating/provider.mdx:278 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### SDKv2"]
./website/docs/plugin/framework/migrating/provider.mdx:293 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Framework"]
./website/docs/plugin/framework/migrating/provider.mdx:313 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Migration Notes"]
./website/docs/plugin/framework/migrating/provider.mdx:321 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Example"]
./website/docs/plugin/framework/migrating/provider.mdx:335 MD036/no-emphasis-as-heading/no-emphasis-as-header Emphasis used instead of a heading [Context: "SDKv2"]
./website/docs/plugin/framework/migrating/provider.mdx:358 MD036/no-emphasis-as-heading/no-emphasis-as-header Emphasis used instead of a heading [Context: "Framework"]
./website/docs/plugin/framework/migrating/testing.mdx:109 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Example"]
./website/docs/plugin/framework/migrating/testing.mdx:119 MD036/no-emphasis-as-heading/no-emphasis-as-header Emphasis used instead of a heading [Context: "SDKv2"]
./website/docs/plugin/framework/migrating/testing.mdx:146 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Framework"]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive me - is the problem that we have duplicate headings? My opinion is that they are needed here, but let me know if you disagree!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 2 things that are being flagged by the linter are:

  • Duplicate headings (e.g., where we have ### SDKv2 multiple times).
  • Emphasis used instead of heading (e.g., SDKv2) rather than #### SDKv2, such as in the ### Example sections.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the removal of **SDKv2** and **Framework**, we now have the following:

terraform-plugin-framework % markdownlint --disable MD013 -- ./website/docs/plugin/framework/migrating/*
./website/docs/plugin/framework/migrating/testing.mdx:108 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "### Example"]
./website/docs/plugin/framework/migrating/testing.mdx:118 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "#### SDKv2"]
./website/docs/plugin/framework/migrating/testing.mdx:144 MD024/no-duplicate-heading/no-duplicate-header Multiple headings with the same content [Context: "#### Framework"]

In SDKv2, attributes are defined by the `Schema` field in the provider, resource, or data source schema. The `Schema`
field maps each attribute name (string) to the attribute's `schema.Schema` struct. Both resources and data sources are
defined using the `schema.Resource` struct.

The following code shows a basic implementation of attribute schema for a provider in SDKv2.

```go
func ProviderExample() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
/* ... */
},
```

In SDKv2, resource and data source attributes are defined the same way on their respective types.

```go
func resourceExample() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
/* ... */
```
## Framework

In the Framework, you define attributes by setting the `Attributes` field on your provider, resource, or data type's
schema, as returned by the `GetSchema` function. The `tfsdk.Schema` type returned by `GetSchema` includes an
`Attributes` field that maps each attribute name (string) to the attribute's `tfsdk.Attribute` struct.

The following code shows how to define an attribute for a resource with the Framework.

```go
func (d *resourceTypeExample) GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
Attributes: map[string]tfsdk.Attribute{
"example": {
/* ... */
```

The Framework defines the `tfsdk.Attribute` struct as follows.

```go
type Attribute struct {
Type attr.Type
Attributes NestedAttributes
Description string
MarkdownDescription string
Required bool
Optional bool
Computed bool
Sensitive bool
DeprecationMessage string
Validators []AttributeValidator
PlanModifiers AttributePlanModifiers
}
```
## Migration Notes
Remember the following differences between SDKv2 and the Framework when completing the migration.

- In SDKv2, attributes are defined by a map from attribute names to `schema.Schema` structs in the `Schema` field of
your resource's schema. In the Framework, attributes are defined by a map from attribute names to `tfsdk.Attribute`
structs in your resource's schema, which is returned by the `GetSchema` function.
- There are several differences between the implementation of attributes in SDKv2 and the Framework. Refer to the other
pages in the Attributes & Blocks section of this migration guide for more details.

## Example

The following examples show how to migrate portions of the
[http](https://github.com/hashicorp/terraform-provider-http) provider.

For a complete example, clone the
`terraform-provider-http` repository and compare the `data_source.go` file in
[v2.2.0](https://github.com/hashicorp/terraform-provider-http/blob/v2.2.0/internal/provider/data_source.go)
and the `data_source_http.go` file in
bendbennett marked this conversation as resolved.
Show resolved Hide resolved
[v3.0.1](https://github.com/hashicorp/terraform-provider-http/blob/v3.0.1/internal/provider/data_source_http.go).


### SDKv2

The following example from the `data_source.go` file shows the implementation of the `url` attribute for the `http`
data source.

```go
func dataSource() *schema.Resource {
return &schema.Resource{
/* ... */
Schema: map[string]*schema.Schema{
"url": {
Description: "The URL for the request. Supported schemes are `http` and `https`.",
Type: schema.TypeString,
Required: true,
},
```


### Framework

The following shows the same section of provider code after the migration.

This code implements the `url` attribute for the `http` data source with the Framework.

```go
func (d *httpDataSourceType) GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
...
Attributes: map[string]tfsdk.Attribute{
"url": {
Description: "The URL for the request. Supported schemes are `http` and `https`.",
Type: types.StringType,
Required: true,
},
...
```
@@ -0,0 +1,107 @@
---
page_title: 'Computed Blocks: Migrating from SDKv2 to the Framework'
description: >-
Migrate computed blocks from SDKv2 to attribute validators in the plugin Framework.
---

# Computed Blocks

Some providers, resources, and data sources include repeatable nested blocks in their attributes. Some blocks contain
fields with `Computed: true`, which means that the provider code can define the value or that it could come from the
output of terraform apply (e.g., the ID of an EC2 instance). Refer to [Schemas - Blocks](/plugin/framework/FIXME) in the
Framework documentation for details.
bendbennett marked this conversation as resolved.
Show resolved Hide resolved

This page explains how to migrate computed blocks from SDKv2 to the Framework. Refer to
[Blocks](/plugin/framework/migrating/attributes-blocks/blocks) if you are looking for information about migrating blocks
that do not contain computed fields.
bendbennett marked this conversation as resolved.
Show resolved Hide resolved

## SDKv2

In SDKv2, blocks are defined by an attribute whose type is `TypeList`, or `TypeSet` and whose `Elem` field is set to a
`schema.Resource` that contains a map of the block's attribute names to corresponding `schemaSchema` structs.
bendbennett marked this conversation as resolved.
Show resolved Hide resolved

```go
map[string]*schema.Schema{
"example": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"nested_example": {
Type: schema.TypeString,
Computed: true,
...
```

## Framework

In the Framework, when working with protocol version 5, computed blocks are implemented using an attribute with a `Type`
of `types.ListType` which has an `ElemType` of `types.ObjectType`.
bendbennett marked this conversation as resolved.
Show resolved Hide resolved

When working with protocol version 6, we recommend that you define computed blocks using nested attributes.

```go
map[string]tfsdk.Attribute{
"example": {
Computed: true,
Type: types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_example": types.StringType,
...

```
## Migration Notes

- When using protocol version 5 specify `ElemType` as `types.ObjectType` when migrating blocks that are computed from SDKv2 to Framework.
- When using protocol version 6, use [nested attributes](https://www.terraform.io/plugin/framework/schemas#attributes-1) when migrating blocks that are computed from SDKv2 to Framework.

## Example

The following examples show how to migrate portions of the [tls](https://github.com/hashicorp/terraform-provider-tls)
provider.

For a complete example, clone the
`terraform-provider-tls` repository and compare the `data_source_certificate.go` file in
[v3.4.0](https://github.com/hashicorp/terraform-provider-tls/blob/v3.4.0/internal/provider/data_source_certificate.go)
with
[v4.0.1](https://github.com/hashicorp/terraform-provider-tls/blob/v4.0.1/internal/provider/data_source_certificate.go).

### SDKv2

The following example from the `data_source_certificate.go` file shows the implementation of the `certificates` nested
block on the `certificate` data source's schema.

```go
Schema: map[string]*schema.Schema{
"certificates": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"signature_algorithm": {
Type: schema.TypeString,
Computed: true,
...
},
```

### Framework

The following shows the same section of provider code after the migration.

This code defines the `certificates` block as an attribute on the `certificate` data source's schema, where the
`types.ObjectType` is being used to define the nested block.

```go
map[string]tfsdk.Attribute{
"certificates": {
Type: types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"signature_algorithm": types.StringType,
},
},
Computed: true,
...
```