From 87aeb1f6e7fd68520a6c281040ba61fd0115c5de Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 9 Mar 2023 17:28:15 -0500 Subject: [PATCH 01/11] Removed testing page (already added in plugin-testing) --- website/data/plugin-sdkv2-nav-data.json | 4 - .../plugin/sdkv2/best-practices/index.mdx | 13 +- .../plugin/sdkv2/best-practices/testing.mdx | 388 ------------------ 3 files changed, 1 insertion(+), 404 deletions(-) delete mode 100644 website/docs/plugin/sdkv2/best-practices/testing.mdx diff --git a/website/data/plugin-sdkv2-nav-data.json b/website/data/plugin-sdkv2-nav-data.json index d391d55a603..1b586b92fe7 100644 --- a/website/data/plugin-sdkv2-nav-data.json +++ b/website/data/plugin-sdkv2-nav-data.json @@ -133,10 +133,6 @@ "title": "Handling Sensitive Data", "path": "best-practices/sensitive-state" }, - { - "title": "Testing Patterns", - "path": "best-practices/testing" - }, { "title": "Versioning and Changelog", "path": "best-practices/versioning" diff --git a/website/docs/plugin/sdkv2/best-practices/index.mdx b/website/docs/plugin/sdkv2/best-practices/index.mdx index 7391ac675bb..6cd4bc6a1f9 100644 --- a/website/docs/plugin/sdkv2/best-practices/index.mdx +++ b/website/docs/plugin/sdkv2/best-practices/index.mdx @@ -2,7 +2,7 @@ page_title: Plugin Development - Best Practices description: >- Patterns that ensure a consistent user experience, including naming, - deprecation, beta features, testing, and versioning. + deprecation, beta features, and versioning. --- # Terraform Plugin Best Practices @@ -53,15 +53,6 @@ Drift][drift], we cover some best practices to ensure Terraform's statefile is an accurate reflection of reality, to provide accurate plan and apply functionality. -## Testing Patterns - -Terraform developers are encouraged to write acceptance tests that create real -resource to verify the behavior of plugins, ensuring a reliable and safe -way to manage infrastructure. In [Testing Patterns][testing-patterns] we cover -some basic acceptance tests that almost all resources should have to validate -not only the functionality of the resource, but that the resource behaves as -Terraform would expect. - ## Versioning and Changelog Terraform development serves two distinct audiences: those writing plugin code @@ -77,6 +68,4 @@ release versions and how to relay changes through documentation. [drift]: /terraform/plugin/sdkv2/best-practices/detecting-drift -[testing-patterns]: /terraform/plugin/sdkv2/best-practices/testing - [versioning]: /terraform/plugin/sdkv2/best-practices/versioning diff --git a/website/docs/plugin/sdkv2/best-practices/testing.mdx b/website/docs/plugin/sdkv2/best-practices/testing.mdx deleted file mode 100644 index 1cf644d2dae..00000000000 --- a/website/docs/plugin/sdkv2/best-practices/testing.mdx +++ /dev/null @@ -1,388 +0,0 @@ ---- -page_title: Plugin Development - Testing Patterns -description: |- - Testing Patterns covers essential acceptance test patterns to implement for - Terraform resources. ---- - -# Testing Patterns - -In [Testing Terraform Plugins][1] we introduce Terraform’s Testing Framework, -providing reference for its functionality and introducing the basic parts of -writing acceptance tests. In this section we’ll cover some test patterns that -are common and considered a best practice to have when developing and verifying -your Terraform plugins. At time of writing these guides are particular to -Terraform Resources, but other testing best practices may be added later. - -## Table of Contents - -- [Built-in Patterns](#built-in-patterns) -- [Basic test to verify attributes](#basic-test-to-verify-attributes) -- [Update test verify configuration changes](#update-test-verify-configuration-changes) -- [Expecting errors or non-empty plans](#expecting-errors-or-non-empty-plans) -- [Regression tests](#regression-tests) - -## Built-in Patterns - -Acceptance tests use [TestCases][2] to construct scenarios that can be evaluated -with Terraform’s lifecycle of plan, apply, refresh, and destroy. The test -framework has some behaviors built in that provide very basic workflow assurance -tests, such as verifying configurations apply with no diff generated by the next -plan. - -Each TestCase will run any [PreCheck][3] function provided before running the -test, and then any [CheckDestroy][4] functions after the test concludes. These -functions allow developers to verify the state of the resource and test before -and after it runs. - -When a test is ran, Terraform runs plan, apply, refresh, and then final plan for -each [TestStep][5] in the TestCase. If the last plan results in a non-empty -plan, Terraform will exit with an error. This enables developers to ensure that -configurations apply cleanly. In the case of introducing regression tests or -otherwise testing specific error behavior, TestStep offers a boolean field -[ExpectNonEmptyPlan][6] as well [ExpectError][7] regex field to specify ways the -test framework can handle expected failures. If these properties are omitted and -either a non-empty plan occurs or an error encountered, Terraform will fail the -test. - -After all TestSteps have been ran, Terraform then runs destroy, and ends by -running any CheckDestroy function provided. - -[Back to top](#table-of-contents) - -## Basic test to verify attributes - -The most basic resource acceptance test should use what is likely to be a common -configuration for the resource under test, and verify that Terraform can -correctly create the resource, and that resources attributes are what Terraform -expects them to be. At a high level, the first basic test for a resource should -establish the following: - -- Terraform can plan and apply a common resource configuration without error. -- Verify the expected attributes are saved to state, and contain the values - expected. -- Verify the values in the remote API/Service for the resource match - what is stored in state. -- Verify that a subsequent terraform plan does not produce - a diff/change. - -The first and last item are provided by the test framework as described above in -**Built-in Patterns**. The middle items are implemented by composing a series of -Check Functions as described in [Acceptance Tests: TestSteps][8]. - -To verify attributes are saved to the state file correctly, use a combination of -the built-in check functions provided by the testing framework. See [Built-in -Check Functions][9] to see available functions. - -Checking the values in a remote API generally consists of two parts: a function -to verify the corresponding object exists remotely, and a separate function to -verify the values of the object. By separating the check used to verify the -object exists into its own function, developers are free to re-use it for all -TestCases as a means of retrieving it’s values, and can provide custom check -functions per TestCase to verify different attributes or scenarios specific to -that TestCase. - -Here’s an example test, with in-line comments to demonstrate the key parts of a -basic test. - -```go -package example - -// example.Widget represents a concrete Go type that represents an API resource -func TestAccExampleWidget_basic(t *testing.T) { - var widget example.Widget - - // generate a random name for each widget test run, to avoid - // collisions from multiple concurrent tests. - // the acctest package includes many helpers such as RandStringFromCharSet - // See https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/helper/acctest - rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckExampleResourceDestroy, - Steps: []resource.TestStep{ - { - // use a dynamic configuration with the random name from above - Config: testAccExampleResource(rName), - // compose a basic test, checking both remote and local values - Check: resource.ComposeTestCheckFunc( - // query the API to retrieve the widget object - testAccCheckExampleResourceExists("example_widget.foo", &widget), - // verify remote values - testAccCheckExampleWidgetValues(widget, rName), - // verify local values - resource.TestCheckResourceAttr("example_widget.foo", "active", "true"), - resource.TestCheckResourceAttr("example_widget.foo", "name", rName), - ), - }, - }, - }) -} - -func testAccCheckExampleWidgetValues(widget *example.Widget, name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if *widget.Active != true { - return fmt.Errorf("bad active state, expected \"true\", got: %#v", *widget.Active) - } - if *widget.Name != name { - return fmt.Errorf("bad name, expected \"%s\", got: %#v", name, *widget.Name) - } - return nil - } -} - -// testAccCheckExampleResourceExists queries the API and retrieves the matching Widget. -func testAccCheckExampleResourceExists(n string, widget *example.Widget) resource.TestCheckFunc { - return func(s *terraform.State) error { - // find the corresponding state object - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - // retrieve the configured client from the test setup - conn := testAccProvider.Meta().(*ExampleClient) - resp, err := conn.DescribeWidget(&example.DescribeWidgetsInput{ - WidgetIdentifier: rs.Primary.ID, - }) - - if err != nil { - return err - } - - if resp.Widget == nil { - return fmt.Errorf("Widget (%s) not found", rs.Primary.ID) - } - - // assign the response Widget attribute to the widget pointer - *widget = *resp.Widget - - return nil - } -} - -// testAccExampleResource returns an configuration for an Example Widget with the provided name -func testAccExampleResource(name string) string { - return fmt.Sprintf(` -resource "example_widget" "foo" { - active = true - name = "%s" -}`, name) -} -``` - -This example covers all the items needed for a basic test, and will be -referenced or added to in the other test cases to come. - -[Back to top](#table-of-contents) - -## Update test verify configuration changes - -A basic test covers a simple configuration that should apply successfully and -with no follow up differences in state. To verify a resource correctly applies -updates, the second most common test found is an extension of the basic test, -that simply applies another `TestStep` with a modified version of the original -configuration. - -Below is an example test, copied and modified from the basic test. Here we -preserve the `TestStep` from the basic test, but we add an additional -`TestStep`, changing the configuration and rechecking the values, with a -different configuration function `testAccExampleResourceUpdated` and check -function `testAccCheckExampleWidgetValuesUpdated` for verifying the values. - -```go -func TestAccExampleWidget_update(t *testing.T) { - var widget example.Widget - rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckExampleResourceDestroy, - Steps: []resource.TestStep{ - { - // use a dynamic configuration with the random name from above - Config: testAccExampleResource(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckExampleResourceExists("example_widget.foo", &widget), - testAccCheckExampleWidgetValues(widget, rName), - resource.TestCheckResourceAttr("example_widget.foo", "active", "true"), - resource.TestCheckResourceAttr("example_widget.foo", "name", rName), - ), - }, - { - // use a dynamic configuration with the random name from above - Config: testAccExampleResourceUpdated(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckExampleResourceExists("example_widget.foo", &widget), - testAccCheckExampleWidgetValuesUpdated(widget, rName), - resource.TestCheckResourceAttr("example_widget.foo", "active", "false"), - resource.TestCheckResourceAttr("example_widget.foo", "name", rName), - ), - }, - }, - }) -} - -func testAccCheckExampleWidgetValuesUpdated(widget *example.Widget, name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if *widget.Active != false { - return fmt.Errorf("bad active state, expected \"false\", got: %#v", *widget.Active) - } - if *widget.Name != name { - return fmt.Errorf("bad name, expected \"%s\", got: %#v", name, *widget.Name) - } - return nil - } -} - -// testAccExampleResource returns an configuration for an Example Widget with the provided name -func testAccExampleResourceUpdated(name string) string { - return fmt.Sprintf(` -resource "example_widget" "foo" { - active = false - name = "%s" -}`, name) -} -``` - -It’s common for resources to just have the above update test, as it is a -superset of the basic test. So long as the basics are covered, combining the two -tests is sufficient as opposed to having two separate tests. - -[Back to top](#table-of-contents) - -## Expecting errors or non-empty plans - -The number of acceptance tests for a given resource typically start small with -the basic and update scenarios covered. Other tests should be added to -demonstrate common expected configurations or behavior scenarios for a given -resource, such as typical updates or changes to configuration, or exercising -logic that uses polling for updates such as an autoscaling group adding or -draining instances. - -It is possible for scenarios to exist where a valid configuration (no errors -during `plan`) would result in a non-empty `plan` after successfully running -`terraform apply`. This is typically due to a valid but otherwise -misconfiguration of the resource, and is generally undesirable. Occasionally it -is useful to intentionally create this scenario in an early `TestStep` in order -to demonstrate correcting the state with proper configuration in a follow-up -`TestStep`. Normally a `TestStep` that results in a non-empty plan would fail -the test after apply, however developers can use the `ExpectNonEmptyPlan` -attribute to prevent failure and allow the `TestCase` to continue: - -```go -func TestAccExampleWidget_expectPlan(t *testing.T) { - var widget example.Widget - rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckExampleResourceDestroy, - Steps: []resource.TestStep{ - { - // use an incomplete configuration that we expect - // to result in a non-empty plan after apply - Config: testAccExampleResourceIncomplete(rName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("example_widget.foo", "name", rName), - ), - ExpectNonEmptyPlan: true, - }, - { - // apply the complete configuration - Config: testAccExampleResourceComplete(rName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("example_widget.foo", "name", rName), - ), - }, - }, - }) -} -``` - -In addition to `ExpectNonEmptyPlan`, `TestStep` also exposes an `ExpectError` -hook, allowing developers to test configuration that they expect to produce an -error, such as configuration that fails schema validators: - -```go -func TestAccExampleWidget_expectError(t *testing.T) { - var widget example.Widget - rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckExampleResourceDestroy, - Steps: []resource.TestStep{ - { - // use a configuration that we expect to fail a validator - // on the resource Name attribute, which only allows alphanumeric - // characters - Config: testAccExampleResourceError(rName + "*$%%^"), - // No check function is given because we expect this configuration - // to fail before any infrastructure is created - ExpectError: regexp.MustCompile("Widget names may only contain alphanumeric characters"), - }, - }, - }) -} -``` - -`ExpectError` expects a valid regular expression, and the error message must -match in order to consider the error as expected and allow the test to pass. If -the regular expression does not match, the `TestStep` fails explaining that the -configuration did not produce the error expected. - -[Back to top](#table-of-contents) - -## Regression tests - -As resources are put into use, issues can arise as bugs that need to be fixed -and released in a new version. Developers are encouraged to introduce regression -tests that demonstrate not only any bugs reported, but that code modified to -address any bug is verified as fixing the issues. These regression tests should -be named and documented appropriately to identify the issue(s) they demonstrate -fixes for. When possible the documentation for a regression test should include -a link to the original bug report. - -An ideal bug fix would include at least 2 commits to source control: - -A single commit introducing the regression test, verifying the issue(s) 1 or -more commits that modify code to fix the issue(s) - -This allows other developers to independently verify that a regression test -indeed reproduces the issue by checking out the source at that commit first, and -then advancing the revisions to evaluate the fix. - -[Back to top](#table-of-contents) - -# Conclusion - -Terraform’s [Testing Framework][1] allows for powerful, iterative acceptance -tests that enable developers to fully test the behavior of Terraform plugins. By -following the above best practices, developers can ensure their plugin behavies -correctly across the most common use cases and everyday operations users will -have using their plugins, and ensure that Terraform remains a world-class tool -for safely managing infrastructure. - -[1]: /terraform/plugin/sdkv2/testing - -[2]: /terraform/plugin/sdkv2/testing/acceptance-tests/testcase - -[3]: /terraform/plugin/sdkv2/testing/acceptance-tests/testcase#precheck - -[4]: /terraform/plugin/sdkv2/testing/acceptance-tests/testcase#checkdestroy - -[5]: /terraform/plugin/sdkv2/testing/acceptance-tests/teststep - -[6]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource#TestStep.ExpectNonEmptyPlan - -[7]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource#TestStep.ExpectError - -[8]: /terraform/plugin/sdkv2/testing/acceptance-tests/teststep#check-functions - -[9]: /terraform/plugin/sdkv2/testing/acceptance-tests/teststep#builtin-check-functions From 2ff23a42d7cfc0e770c55a95da72fff368359d03 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 9 Mar 2023 17:46:33 -0500 Subject: [PATCH 02/11] removed other language page --- website/data/plugin-sdkv2-nav-data.json | 4 --- .../sdkv2/best-practices/other-languages.mdx | 30 ------------------- 2 files changed, 34 deletions(-) delete mode 100644 website/docs/plugin/sdkv2/best-practices/other-languages.mdx diff --git a/website/data/plugin-sdkv2-nav-data.json b/website/data/plugin-sdkv2-nav-data.json index 1b586b92fe7..85097c1a0ed 100644 --- a/website/data/plugin-sdkv2-nav-data.json +++ b/website/data/plugin-sdkv2-nav-data.json @@ -136,10 +136,6 @@ { "title": "Versioning and Changelog", "path": "best-practices/versioning" - }, - { - "title": "Writing Non-Go Providers", - "path": "best-practices/other-languages" } ] } diff --git a/website/docs/plugin/sdkv2/best-practices/other-languages.mdx b/website/docs/plugin/sdkv2/best-practices/other-languages.mdx deleted file mode 100644 index bde867168c6..00000000000 --- a/website/docs/plugin/sdkv2/best-practices/other-languages.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -page_title: Plugin Development - Non-Go Providers -description: Information about writing providers in programming languages other than Go. ---- - -# Writing Non-Go Providers - -There has been a lot of interest in writing providers using languages other -than Go, and people frequently ask for information on how to go about doing -that. The Terraform team's policy at this time is that while it is technically -possible to write providers in languages other than Go, our tooling, -documentation, and ecosystem will all assume your provider is being written in -and distributed as Go code for the time being. This means we will not be -writing any documentation on how to build a non-Go provider, nor will we be -providing support or answering questions about it. - -While it is possible to write a non-Go provider, thanks to Terraform's use of -the gRPC protocol, it is harder than it may appear at first glance. Multiple -packages, from encoders and decoders to Terraform's type system, would all need -to be reimplemented in that new language. The Plugin SDK would also need to be -reimplemented, which is not a trivial challenge. And the way non-Go providers -would interact with the Registry, `terraform init`, and other pieces of the -Terraform ecosystem is unclear. - -At this point, our efforts are focused on providing the best development -experience for Terraform providers written in Go that we can. The Terraform -provider development experience is still evolving aggressively, as is -Terraform's interface for providers. We may reconsider this policy once there -is a more stable interface to build on and our development experience with Go -has matured and evolved sufficiently. From 6fcc98316c4d4070d709344253c1583658c0c316 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 9 Mar 2023 17:59:58 -0500 Subject: [PATCH 03/11] removed versioning page --- .github/CONTRIBUTING.md | 4 +- website/data/plugin-sdkv2-nav-data.json | 4 - .../sdkv2/best-practices/deprecations.mdx | 2 +- .../plugin/sdkv2/best-practices/index.mdx | 13 +- .../sdkv2/best-practices/versioning.mdx | 141 ------------------ .../docs/plugin/sdkv2/resources/import.mdx | 2 +- 6 files changed, 5 insertions(+), 161 deletions(-) delete mode 100644 website/docs/plugin/sdkv2/best-practices/versioning.mdx diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e08542dc19d..6063af5a54e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -125,7 +125,7 @@ Dependency management is performed by [dependabot](https://docs.github.com/en/co HashiCorp’s open-source projects have always maintained user-friendly, readable CHANGELOGs that allow practitioners and developers to tell at a glance whether a release should have any effect on them, and to gauge the risk of an upgrade. We follow Terraform Plugin -[changelog specifications](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#changelog-specification). +[changelog specifications](https://developer.hashicorp.com/terraform/plugin/best-practices/versioning#changelog-specification). #### Changie Automation Tool This project uses the [Changie](https://changie.dev/) automation tool for changelog automation. @@ -136,7 +136,7 @@ After Changie is installed on your local machine, run: ```bash changie new ``` -and choose a `kind` of change corresponding to the Terraform Plugin [changelog categories](https://developer.hashicorp.com/terraform/plugin/sdkv2/best-practices/versioning#categorization) +and choose a `kind` of change corresponding to the Terraform Plugin [changelog categories](https://developer.hashicorp.com/terraform/plugin/best-practices/versioning#categorization) Fill out the body field following the entry format. Changie will then prompt for a Github issue or pull request number. diff --git a/website/data/plugin-sdkv2-nav-data.json b/website/data/plugin-sdkv2-nav-data.json index 85097c1a0ed..8d08a872946 100644 --- a/website/data/plugin-sdkv2-nav-data.json +++ b/website/data/plugin-sdkv2-nav-data.json @@ -132,10 +132,6 @@ { "title": "Handling Sensitive Data", "path": "best-practices/sensitive-state" - }, - { - "title": "Versioning and Changelog", - "path": "best-practices/versioning" } ] } diff --git a/website/docs/plugin/sdkv2/best-practices/deprecations.mdx b/website/docs/plugin/sdkv2/best-practices/deprecations.mdx index 7f0f5db4b0c..1152095d4c9 100644 --- a/website/docs/plugin/sdkv2/best-practices/deprecations.mdx +++ b/website/docs/plugin/sdkv2/best-practices/deprecations.mdx @@ -7,7 +7,7 @@ description: 'Recommendations for deprecations, removals, and renames.' Terraform is trusted for managing many facets of infrastructure across many organizations. Part of that trust is due to consistent versioning guidelines and setting expectations for various levels of upgrades. Ensuring backwards compatibility for all patch and minor releases, potentially in concert with any upcoming major changes, is recommended and supported by the Terraform development framework. This allows operators to iteratively update their Terraform configurations rather than require massive refactoring. -This guide is designed to walk through various scenarios where existing Terraform functionality requires future removal, while maintaining backwards compatibility. Further information about the versioning terminology (e.g. `MAJOR`.`MINOR`.`PATCH`) in this guide can be found in [the versioning guidelines documentation](/terraform/plugin/sdkv2/best-practices/versioning). +This guide is designed to walk through various scenarios where existing Terraform functionality requires future removal, while maintaining backwards compatibility. Further information about the versioning terminology (e.g. `MAJOR`.`MINOR`.`PATCH`) in this guide can be found in [the versioning guidelines documentation](/terraform/plugin/best-practices/versioning). ~> **NOTE:** Removals should only ever occur in `MAJOR` version upgrades. diff --git a/website/docs/plugin/sdkv2/best-practices/index.mdx b/website/docs/plugin/sdkv2/best-practices/index.mdx index 6cd4bc6a1f9..1d4f6361bf2 100644 --- a/website/docs/plugin/sdkv2/best-practices/index.mdx +++ b/website/docs/plugin/sdkv2/best-practices/index.mdx @@ -2,7 +2,7 @@ page_title: Plugin Development - Best Practices description: >- Patterns that ensure a consistent user experience, including naming, - deprecation, beta features, and versioning. + deprecation, and beta features. --- # Terraform Plugin Best Practices @@ -53,19 +53,8 @@ Drift][drift], we cover some best practices to ensure Terraform's statefile is an accurate reflection of reality, to provide accurate plan and apply functionality. -## Versioning and Changelog - -Terraform development serves two distinct audiences: those writing plugin code -and those implementing them. By clearly and consistently allowing operators to -easily understand changes in plugin implementation via version numbering and -documenting those changes, a trust is formed between the two audiences. In -[Versioning and Changelog][versioning] we cover some guidelines when deciding -release versions and how to relay changes through documentation. - [naming]: /terraform/plugin/sdkv2/best-practices/naming [deprecations]: /terraform/plugin/sdkv2/best-practices/deprecations [drift]: /terraform/plugin/sdkv2/best-practices/detecting-drift - -[versioning]: /terraform/plugin/sdkv2/best-practices/versioning diff --git a/website/docs/plugin/sdkv2/best-practices/versioning.mdx b/website/docs/plugin/sdkv2/best-practices/versioning.mdx deleted file mode 100644 index c65493c8ef2..00000000000 --- a/website/docs/plugin/sdkv2/best-practices/versioning.mdx +++ /dev/null @@ -1,141 +0,0 @@ ---- -page_title: Plugin Development - Versioning Best Practices -description: Recommendations for version numbering and documentation. ---- - -# Versioning and Changelog - -Given the breadth of available Terraform plugins, ensuring a consistent experience across them requires a standard guideline for compatibility promises. These guidelines are enforced for plugins released by HashiCorp and are recommended for all community plugins. - -## Versioning Specification - -Observing that Terraform plugins are in many ways analogous to shared libraries in a programming language, we adopted a version numbering scheme that follows the guidelines of [Semantic Versioning](http://semver.org/). In summary, this means that with a version number of the form `MAJOR`.`MINOR`.`PATCH`, the following meanings apply: - -- Increasing only the patch number suggests that the release includes only bug fixes, and is intended to be functionally equivalent. -- Increasing the minor number suggests that new features have been added but that existing functionality remains broadly compatible. -- Increasing the major number indicates that significant breaking changes have been made, and thus extra care or attention is required during an upgrade. To allow practitioners sufficient time and opportunity to upgrade to the latest version of the provider, we recommend releasing major versions no more than once per year. Releasing major versions more frequently could present a barrier to adoption due to the effort required to upgrade. - -Version numbers above `1.0.0` signify stronger compatibility guarantees, based on the rules above. Each increasing level can also contain changes of the lower level (e.g. `MINOR` can contain `PATCH` changes). - -### Example Major Number Increments - -Increasing the `MAJOR` number is intended to signify potentially breaking changes. - -Within Terraform provider development, some examples include: - -- Removing a resource or data source -- Removing an attribute (e.g. switching to `Removed` on an attribute or removing the attribute definition altogether) -- Renaming a resource or data source -- Renaming an attribute -- Changing fundamental provider behaviors (e.g. authentication or configuration precedence) -- Changing resource import ID format -- Changing resource ID format -- Changing attribute type where the new type is functionally incompatible (including but not limited to changing `TypeSet` to `TypeList` and `TypeList` to `TypeSet`) -- Changing attribute format (e.g. changing a timestamp from epoch time to a string) -- Changing attribute default value that is incompatible with previous Terraform states (e.g. `Default: "one"` to `Default: "two"`) -- Adding an attribute default value that does not match the API default - -### Example Minor Number Increments - -`MINOR` increments are intended to signify the availability of new functionality or deprecations of existing functionality without breaking changes to the previous version. - -Within Terraform provider development, some examples include: - -- Marking a resource or data source as deprecated -- Marking an attribute as deprecated -- Adding a new resource or data source -- Aliasing an existing resource or data source -- Implementing new attributes within the provider configuration or an existing resource or data source -- Implementing new validation within an existing resource or data source -- Changing attribute type where the new type is functionally compatible (e.g. `TypeInt` to `TypeFloat`) - -### Example Patch Number Increments - -Increasing the `PATCH` number is intended to signify mainly bug fixes and to be functionally equivalent with the previous version. - -Within Terraform provider development, some examples include: - -- Fixing an interaction with the remote API or Terraform state drift detection (e.g. broken create, read, update, or delete functionality) -- Fixing attributes to match behavior with resource code (e.g. removing `Optional` when an attribute can not be configured in the remote API) -- Fixing attributes to match behavior with the remote API (e.g. changing `Required` to `Optional`, fixing validation) - -## Changelog Specification - -For better operator experience, we provide a standardized format so development information is available across all providers consistently. The changelog should live in a top level file in the project, named `CHANGELOG` or `CHANGELOG.md`. We generally recommend that the changelog is updated outside of pull requests unless a clear process is setup for handling merge conflicts. - -### Version Headers - -The upcoming release version number is always at the top of the file and is marked specifically as `(Unreleased)`, with other previously released versions below. - -~> **NOTE:** For HashiCorp released providers, the release process will replace the "Unreleased" header with the current date. This line must be present with the target release version to successfully release that version. - -```text -## X.Y.Z (Unreleased) - -... - - -## A.B.C (Month Day, Year) - -... -``` - -### Categorization - -Information in the changelog should broken down as follows: - -- **BACKWARDS INCOMPATIBILITIES** or **BREAKING CHANGES**: This section documents in brief any incompatible changes and how to handle them. This should only be present in major version upgrades. -- **NOTES**: Additional information for potentially unexpected upgrade behavior, upcoming deprecations, or to highlight very important crash fixes (e.g. due to upstream API changes) -- **FEATURES**: These are major new improvements that deserve a special highlight, such as a new resource or data source. -- **IMPROVEMENTS** or **ENHANCEMENTS**: Smaller features added to the project such as a new attribute for a resource. -- **BUG FIXES**: Any bugs that were fixed. - -These should be displayed as left aligned text with new lines above and below: - -```text - -CATEGORY: - -``` - -### Entry Format - -Each entry under a category should use the following format: - -```text -* subsystem: Descriptive message [GH-1234] -``` - -For provider development typically the "subsystem" is the resource or data source affected e.g. `resource/load_balancer`, or `provider` if the change affects whole provider (e.g. authentication logic). Each bullet also references the corresponding pull request number that contained the code changes, in the format of `[GH-####]` (for HashiCorp released plugins, this will be automatically updated on release). - -### Entry Ordering - -To order entries, these basic rules should be followed: - -1. If large cross-cutting changes are present, list them first (e.g. `provider`) -1. Order other entries lexicographically based on subsystem (e.g. `resource/load_balancer` then `resource/subnet`) - -### Example Changelog - -```text -## 1.0.0 (Unreleased) - -BREAKING CHANGES: - -* Resource `network_port` has been removed [GH-1] - -FEATURES: - -* **New Resource:** `cluster` [GH-43] - -IMPROVEMENTS: - -* resource/load_balancer: Add `ATTRIBUTE` argument (support X new functionality) [GH-12] -* resource/subnet: Now better [GH-22, GH-32] - -## 0.2.0 (Month Day, Year) - -FEATURES: - -... -``` diff --git a/website/docs/plugin/sdkv2/resources/import.mdx b/website/docs/plugin/sdkv2/resources/import.mdx index e10120bd5dd..7b2e1c51755 100644 --- a/website/docs/plugin/sdkv2/resources/import.mdx +++ b/website/docs/plugin/sdkv2/resources/import.mdx @@ -80,7 +80,7 @@ The items below are coding/testing styles that should generally be followed when - The `TestStep` including `ImportState` testing should not be performed solely in a separate acceptance test. This duplicates testing infrastructure/time and does not check that all resource configurations import into Terraform properly. - The `TestStep` including `ImportState` should be included in all applicable resource acceptance tests (except those that delete the resource in question, e.g. `_disappears` tests) -- Import implementations should not change existing `Create` function `d.SetId()` calls. [Versioning best practices for Terraform Provider development](/terraform/plugin/sdkv2/best-practices/versioning#example-major-number-increments) notes that changing the resource ID is considered a breaking change for a major version upgrade as it makes the `id` attribute ambiguous between provider versions. +- Import implementations should not change existing `Create` function `d.SetId()` calls. [Versioning best practices for Terraform Provider development](/terraform/plugin/best-practices/versioning#example-major-number-increments) notes that changing the resource ID is considered a breaking change for a major version upgrade as it makes the `id` attribute ambiguous between provider versions. - `ImportStateVerifyIgnore` should only be used where its not possible to `d.Set()` the attribute in the `Read` function (preferable) or `Importer` `State` function. ### Importer State Function From 348975afeb54805489819683bb48ff1814efe8a4 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 9 Mar 2023 18:13:06 -0500 Subject: [PATCH 04/11] removed sensitive state page --- website/data/plugin-sdkv2-nav-data.json | 4 -- .../sdkv2/best-practices/sensitive-state.mdx | 53 ------------------- .../plugin/sdkv2/guides/v2-upgrade-guide.mdx | 4 +- 3 files changed, 2 insertions(+), 59 deletions(-) delete mode 100644 website/docs/plugin/sdkv2/best-practices/sensitive-state.mdx diff --git a/website/data/plugin-sdkv2-nav-data.json b/website/data/plugin-sdkv2-nav-data.json index 8d08a872946..9ae462ede6b 100644 --- a/website/data/plugin-sdkv2-nav-data.json +++ b/website/data/plugin-sdkv2-nav-data.json @@ -128,10 +128,6 @@ { "title": "Detecting Drift", "path": "best-practices/detecting-drift" - }, - { - "title": "Handling Sensitive Data", - "path": "best-practices/sensitive-state" } ] } diff --git a/website/docs/plugin/sdkv2/best-practices/sensitive-state.mdx b/website/docs/plugin/sdkv2/best-practices/sensitive-state.mdx deleted file mode 100644 index b1af62f6a9e..00000000000 --- a/website/docs/plugin/sdkv2/best-practices/sensitive-state.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -page_title: Plugin Development - Sensitive State Best Practices -description: Recommendations for handling sensitive information in state. ---- - -# Handling Sensitive Values in State - -Many organizations use Terraform to manage their entire infrastructure, and -it's inevitable that [sensitive information will find its way into -Terraform](/terraform/language/state/sensitive-data) in these circumstances. There are a -couple of recommended approaches for managing sensitive state in Terraform. - -## Using the `Sensitive` Flag - -When working with a field that contains information likely to be considered -sensitive, it is best to set the -[`Sensitive`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/helper/schema#Schema.Sensitive) -property on its schema to `true`. This will prevent the field's values from -showing up in CLI output and in Terraform Cloud. It will **not encrypt** or obscure -the value in the state, however. - -## Don't Encrypt State - -One experiment that has been attempted is allowing the user to provide a PGP -key and a cipher text, and decrypting the value in the provider code before -using it, storing only the cipher text in state. Another variation on this -approach was providing a PGP key that data from an API would be encrypted with -before being set in state, with nothing being set in the config. - -Both of these approaches are discouraged and will be removed from the -HashiCorp-supported providers over time. This strategy was tailored to a time -when Terraform's state had to be stored in cleartext on any machine running -`terraform apply`, and was meant to provide a bit of security in that scenario. -With the introduction and use of -[remote backends](/terraform/language/settings/backends/configuration) -and especially the availability of -[Terraform Cloud](https://app.terraform.io/), there are now a variety of -backends that will encrypt state at rest and will not store the state in -cleartext on machines running `terraform apply`. This means the original -problem the PGP key pattern was intended to solve has a better-supported -solution, and we're deprecating it in favor of that solution. - -Even without comparing it to full state encryption, PGP key encryption has -major drawbacks. Values encrypted with a PGP key can't be reliably -interpolated, Terraform isn't built to provide a good user experience around a -missing PGP key right now, and the approach needs serious modification to not -violate protocol requirements for Terraform 0.12 and into the future. - -In light of these shortcomings, the encouraged solution at this time is to use -a state backend that supports operations and encryption, and for users whose -security needs cannot be met by that strategy to weigh in on [the issue about -this](https://github.com/hashicorp/terraform/issues/516) to help outline the -gaps in this strategy, so appropriate solutions can be designed for them. diff --git a/website/docs/plugin/sdkv2/guides/v2-upgrade-guide.mdx b/website/docs/plugin/sdkv2/guides/v2-upgrade-guide.mdx index 28a41d323e6..8c1d715d9ae 100644 --- a/website/docs/plugin/sdkv2/guides/v2-upgrade-guide.mdx +++ b/website/docs/plugin/sdkv2/guides/v2-upgrade-guide.mdx @@ -624,9 +624,9 @@ Terraform’s built-in error messaging indicate its removal. ## Removal of `helper/encryption` Package The `helper/encryption` package supports an [anti-pattern that is now -discouraged](/terraform/plugin/sdkv2/best-practices/sensitive-state#don-39-t-encrypt-state), +discouraged](/terraform/plugin/best-practices/sensitive-state#don-t-encrypt-state), so it has been removed. Providers relying on it should see the -[documentation](/terraform/plugin/sdkv2/best-practices/sensitive-state) +[documentation](/terraform/plugin/best-practices/sensitive-state) on that pattern and select an alternative approach. ## Removal of Discouraged Variables, Functions, Types, and Interfaces From c427b254e881514ec6f1e32c43d64bd77a514a6c Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 9 Mar 2023 18:20:04 -0500 Subject: [PATCH 05/11] remove depending on providers --- website/data/plugin-sdkv2-nav-data.json | 4 -- .../best-practices/depending-on-providers.mdx | 53 ------------------- 2 files changed, 57 deletions(-) delete mode 100644 website/docs/plugin/sdkv2/best-practices/depending-on-providers.mdx diff --git a/website/data/plugin-sdkv2-nav-data.json b/website/data/plugin-sdkv2-nav-data.json index 9ae462ede6b..8a5a87719e4 100644 --- a/website/data/plugin-sdkv2-nav-data.json +++ b/website/data/plugin-sdkv2-nav-data.json @@ -117,10 +117,6 @@ "title": "Naming", "path": "best-practices/naming" }, - { - "title": "Depending on Providers", - "path": "best-practices/depending-on-providers" - }, { "title": "Deprecations, Removals, and Renames", "path": "best-practices/deprecations" diff --git a/website/docs/plugin/sdkv2/best-practices/depending-on-providers.mdx b/website/docs/plugin/sdkv2/best-practices/depending-on-providers.mdx deleted file mode 100644 index ef717e93f7f..00000000000 --- a/website/docs/plugin/sdkv2/best-practices/depending-on-providers.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -page_title: Plugin Development - Depending on Providers -description: How to safely depend on providers and understand their interfaces. ---- - -# Depending on Providers - -Terraform's providers are a substantial amount of code, and occasionally it -makes sense to depend on their functionality. The most straightforward and -obvious way to depend on a provider is to depend on the Terraform CLI, but -occasionally it makes sense to rely on a provider in a different context. - -This guide lays out the supported ways to interface with and depend on -Terraform's providers. Unless the provider explicitly states otherwise, no -other compatibility guarantees are provided. - -## Do Not Import Providers as Go Modules - -Terraform's providers are written as Go packages, and they mostly use Go -modules as their dependency management solution. This makes it tempting to -import the provider as a dependency of your Go code, and to call its exposed -interface. This is explicitly an **unsupported** way to interact with providers -and provider maintainers make no guarantees around backwards compatibility or -the continued functioning of code that does this. - -Providers are unable to be imported as Go modules reliably because their -versioning scheme is intended to convey information about the Terraform config -interface the provider presents. It's unable to capture both the configuration -interface _and_ the Go API interface in a useful way, as what is compatible in -one may not be compatible in the other. Rather than give the impression that -the package should be imported by using the `/vX` suffix now mandated for -versions after 2.0.0, providers have chosen to make their incompatibility with -being imported into Go code explicit. - -If you find yourself needing to do this, perhaps one of the methods below will -work for you, and is explicitly supported and covered under versioning policies. -If not, please reach out and [open an issue](https://github.com/hashicorp/terraform/issues/new) -outlining your use case, and we'll work with you to find an appropriate way -to interface with Terraform to meet your use case. - -## Exporting the Schema - -Some projects just care about the schema and resources a provider presents. As -of Terraform 0.12, the `terraform providers schema -json` command can be used -to export a JSON representation of the schemas for the providers used in a -workspace. - -## Using the RPC Protocol - -For projects that actually want to drive the provider, the supported option is to use the [gRPC protocol](https://github.com/hashicorp/terraform/tree/main/docs/plugin-protocol) -and the RPC calls the protocol supplies. This -protocol is the same protocol that drives Terraform's CLI interface, and -it is versioned using a protocol version. It changes relatively infrequently. From cd532444cd6bb36e70878aa8b82a325f0d0d1b3f Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 9 Mar 2023 18:26:19 -0500 Subject: [PATCH 06/11] remove naming page --- website/data/plugin-sdkv2-nav-data.json | 4 - .../plugin/sdkv2/best-practices/index.mdx | 11 +-- .../plugin/sdkv2/best-practices/naming.mdx | 93 ------------------- 3 files changed, 1 insertion(+), 107 deletions(-) delete mode 100644 website/docs/plugin/sdkv2/best-practices/naming.mdx diff --git a/website/data/plugin-sdkv2-nav-data.json b/website/data/plugin-sdkv2-nav-data.json index 8a5a87719e4..27869756df4 100644 --- a/website/data/plugin-sdkv2-nav-data.json +++ b/website/data/plugin-sdkv2-nav-data.json @@ -113,10 +113,6 @@ "title": "Best Practices", "routes": [ { "title": "Overview", "path": "best-practices" }, - { - "title": "Naming", - "path": "best-practices/naming" - }, { "title": "Deprecations, Removals, and Renames", "path": "best-practices/deprecations" diff --git a/website/docs/plugin/sdkv2/best-practices/index.mdx b/website/docs/plugin/sdkv2/best-practices/index.mdx index 1d4f6361bf2..65df39d1235 100644 --- a/website/docs/plugin/sdkv2/best-practices/index.mdx +++ b/website/docs/plugin/sdkv2/best-practices/index.mdx @@ -1,8 +1,7 @@ --- page_title: Plugin Development - Best Practices description: >- - Patterns that ensure a consistent user experience, including naming, - deprecation, and beta features. + Patterns that ensure a consistent user experience, including deprecation and beta features. --- # Terraform Plugin Best Practices @@ -20,12 +19,6 @@ Providers, with a brief description of each, and link to read more. This section is a work in progress, with more sections to come. -## Naming - -[Naming][naming] resources, data sources, and attributes in plugins is how plugin authors -expose their functionality to operators and using patterns common to other plugins -lays the foundation for a good user experience. - ## Deprecations, Removals, and Renames Over time, remote services evolve and better workflows are designed. @@ -53,8 +46,6 @@ Drift][drift], we cover some best practices to ensure Terraform's statefile is an accurate reflection of reality, to provide accurate plan and apply functionality. -[naming]: /terraform/plugin/sdkv2/best-practices/naming - [deprecations]: /terraform/plugin/sdkv2/best-practices/deprecations [drift]: /terraform/plugin/sdkv2/best-practices/detecting-drift diff --git a/website/docs/plugin/sdkv2/best-practices/naming.mdx b/website/docs/plugin/sdkv2/best-practices/naming.mdx deleted file mode 100644 index 583c7e07873..00000000000 --- a/website/docs/plugin/sdkv2/best-practices/naming.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -page_title: Plugin Development - Naming Best Practices -description: |- - Our recommendations for naming resources, data sources, and attributes in - providers. ---- - -## Naming - -Most names in a Terraform provider will be drawn from the upstream API/SDK that -the provider is using. The upstream API names will likely need to be -modified for casing or changing between plural and singular to make -the provider more consistent with the common Terraform practices below. - -### Resource Names - -Resource names are nouns, since resource blocks each represent a single -object Terraform is managing. Resource names must always start with their -containing provider's name followed by an underscore, so a resource from -the provider `postgresql` might be named `postgresql_database`. - -It is preferable to use resource names that will be familiar to those with -prior experience using the service in question, e.g. via a web UI it provides. - -### Data Source Names - -Similar to resource names, data source names should be nouns. The main difference -is that in some cases data sources are used to return a list and can in -those cases be plural. For example the data source -[`aws_availability_zones`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) -in the AWS provider returns a list of availability zones. - -### Attribute Names - -Below is an example of a resource configuration block which illustrates some -general design patterns that can apply across all plugin object types: - -```hcl -resource "aws_instance" "example" { - ami = "ami-408c7f28" - instance_type = "t1.micro" - monitoring = true - vpc_security_group_ids = [ - "sg-1436abcf", - ] - tags = { - Name = "Application Server" - Environment = "production" - } - root_block_device { - delete_on_termination = false - } -} -``` - -Attribute names within Terraform configuration blocks are conventionally named -as all-lowercase with underscores separating words, as shown above. - -Simple single-value attributes, like `ami` and `instance_type` in the above -example, are given names that are singular nouns, to reflect that only one -value is required and allowed. - -Boolean attributes like `monitoring` are usually written also as nouns -describing what is being enabled. However, they can sometimes be named as -verbs if the attribute is specifying whether to take some action, as with the -`delete_on_termination` flag within the `root_block_device` block. - -Boolean attributes are ideally oriented so that `true` means to do something -and `false` means not to do it; it can be confusing to have "negative" flags -that prevent something from happening, since they require the user to follow -a double-negative in order to reason about what value should be provided. - -Some attributes expect list, set or map values. In the above example, -`vpc_security_group_ids` is a set of strings, while `tags` is a map -from strings to strings. Such attributes should be named with _plural_ nouns, -to reflect that multiple values may be provided. - -List and set attributes use the same bracket syntax, and differ only in how -they are described to and used by the user. In lists, the ordering is -significant and duplicate values are often accepted. In sets, the ordering is -_not_ significant and duplicated values are usually _not_ accepted, since -presence or absence is what is important. - -Map blocks use the same syntax as other configuration blocks, but the keys in -maps are arbitrary and not explicitly named by the plugin, so in some cases -(as in this `tags` example) they will not conform to the usual "lowercase with -underscores" naming convention. - -Configuration blocks may contain other sub-blocks, such as `root_block_device` -in the above example. The patterns described above can also apply to such -sub-blocks. Sub-blocks are usually introduced by a singular noun, even if -multiple instances of the same-named block are accepted, since each distinct -instance represents a single object. From 60cd1dde748f3002b67bb4438f389fec3737b156 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Fri, 10 Mar 2023 08:17:22 -0500 Subject: [PATCH 07/11] add to title, no removal --- website/docs/plugin/sdkv2/best-practices/deprecations.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/plugin/sdkv2/best-practices/deprecations.mdx b/website/docs/plugin/sdkv2/best-practices/deprecations.mdx index 1152095d4c9..f0df9490295 100644 --- a/website/docs/plugin/sdkv2/best-practices/deprecations.mdx +++ b/website/docs/plugin/sdkv2/best-practices/deprecations.mdx @@ -1,5 +1,5 @@ --- -page_title: 'Plugin Development - Deprecations, Removals, and Renames Best Practices' +page_title: 'Plugin Development - SDKv2 Deprecations, Removals, and Renames Best Practices' description: 'Recommendations for deprecations, removals, and renames.' --- From 255f3898d8096448c30a9e735dde03ff4a081eb6 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Fri, 10 Mar 2023 08:32:07 -0500 Subject: [PATCH 08/11] update titles --- website/docs/plugin/sdkv2/best-practices/detecting-drift.mdx | 2 +- website/docs/plugin/sdkv2/best-practices/index.mdx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/plugin/sdkv2/best-practices/detecting-drift.mdx b/website/docs/plugin/sdkv2/best-practices/detecting-drift.mdx index 0ae33342867..762c6347022 100644 --- a/website/docs/plugin/sdkv2/best-practices/detecting-drift.mdx +++ b/website/docs/plugin/sdkv2/best-practices/detecting-drift.mdx @@ -1,5 +1,5 @@ --- -page_title: Plugin Development - Detecting Drift +page_title: Plugin Development - SDKv2 Detecting Drift description: |- "Drift" describes changes to infrastructure outside of Terraform. Learn how to ensure that Terraform detects drift so that users will know when their diff --git a/website/docs/plugin/sdkv2/best-practices/index.mdx b/website/docs/plugin/sdkv2/best-practices/index.mdx index 65df39d1235..2aa7d3e2260 100644 --- a/website/docs/plugin/sdkv2/best-practices/index.mdx +++ b/website/docs/plugin/sdkv2/best-practices/index.mdx @@ -1,7 +1,7 @@ --- -page_title: Plugin Development - Best Practices +page_title: Plugin Development - SDKv2 Best Practices description: >- - Patterns that ensure a consistent user experience, including deprecation and beta features. + Patterns that ensure a consistent user experience, including deprecation, beta features, and detecting drift. --- # Terraform Plugin Best Practices From 7f7390aaeb2ccd706f9ac1bf228ac51461c4b5cc Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 13 Mar 2023 15:14:46 -0400 Subject: [PATCH 09/11] updated wording + link --- website/docs/plugin/sdkv2/best-practices/deprecations.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/plugin/sdkv2/best-practices/deprecations.mdx b/website/docs/plugin/sdkv2/best-practices/deprecations.mdx index f0df9490295..3499ad9fa74 100644 --- a/website/docs/plugin/sdkv2/best-practices/deprecations.mdx +++ b/website/docs/plugin/sdkv2/best-practices/deprecations.mdx @@ -682,7 +682,7 @@ The recommended process is as follows: 1. Add `DeprecatedMessage` to the schema definition of the existing (now the "old") resource, noting to use the new resource in the message. 1. Add `!> **WARNING:** This resource is deprecated and will be removed in the next major version` to the documentation of the existing (now the "old") resource, noting to use the new resource. 1. Add the new resource to the provider `ResourcesMap` -1. Follow the rest of the procedures in the [Provider Attribute Removal section](#provider-attribute-removal). +1. Follow the rest of the procedures in the [Provider Data Source or Resource Removal section](#provider-data-source-or-resource-removal). ### Example Resource Renaming @@ -708,7 +708,7 @@ func resourceExampleExistingWidget() *schema.Resource { } ``` -In order to support renaming `example_existing_widget` to `example_new_widget`, this sample can be written as the following to support both attributes simultaneously until the `existing_attribute` is removed: +In order to support renaming `example_existing_widget` to `example_new_widget`, this sample can be written as the following to support both resources simultaneously until the `example_existing_widget` resource is removed: ```go func Provider() terraform.ResourceProvider { From aa8be736b8c8c99968dd96f28970dbd3aac22a25 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Tue, 14 Mar 2023 16:18:22 -0400 Subject: [PATCH 10/11] added callout and modified title/wording in first paragraph --- website/docs/plugin/sdkv2/best-practices/index.mdx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/website/docs/plugin/sdkv2/best-practices/index.mdx b/website/docs/plugin/sdkv2/best-practices/index.mdx index 2aa7d3e2260..adc73454bb9 100644 --- a/website/docs/plugin/sdkv2/best-practices/index.mdx +++ b/website/docs/plugin/sdkv2/best-practices/index.mdx @@ -4,7 +4,13 @@ description: >- Patterns that ensure a consistent user experience, including deprecation, beta features, and detecting drift. --- -# Terraform Plugin Best Practices + + +This best practices section only contains guidance for plugins built with the [legacy SDK](/terraform/plugin/sdkv2). More generic best practices that apply to both legacy SDK and [Plugin Framework](/terraform/plugin/framework) can be found in the [Plugin Development Best Practices](/terraform/plugin/best-practices) section. + + + +# Terraform SDKv2 Best Practices A key feature of Terraform is its plugin system, which separates the details of specific vendor APIs from the shared logic for managing state, managing configuration, @@ -14,10 +20,7 @@ specific cloud provider, allowing each provider to fully support its unique resources and lifecycles and not settling for the lowest common denominator across all provider resources of that type (virtual machines, networks, configuration management systems, et. al). While each provider is unique, over -the years, we accumulated recommended patterns that help ensure a consistent user experience when using Terraform for any given provider. This page describes best practices that generally apply to most -Providers, with a brief description of each, and link to read more. - -This section is a work in progress, with more sections to come. +the years, we accumulated recommended patterns that help ensure a consistent user experience when using Terraform for any given provider. This page describes best practices that generally apply to most Providers built with the legacy SDK, with a brief description of each, and link to read more. ## Deprecations, Removals, and Renames From 02e4d90634f37e7a16b8fa68997d93e92a2b58d7 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 15 Mar 2023 13:47:49 -0400 Subject: [PATCH 11/11] Update website/docs/plugin/sdkv2/best-practices/index.mdx Co-authored-by: Brian Flad --- website/docs/plugin/sdkv2/best-practices/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/plugin/sdkv2/best-practices/index.mdx b/website/docs/plugin/sdkv2/best-practices/index.mdx index adc73454bb9..85d6b2d44e4 100644 --- a/website/docs/plugin/sdkv2/best-practices/index.mdx +++ b/website/docs/plugin/sdkv2/best-practices/index.mdx @@ -6,7 +6,7 @@ description: >- -This best practices section only contains guidance for plugins built with the [legacy SDK](/terraform/plugin/sdkv2). More generic best practices that apply to both legacy SDK and [Plugin Framework](/terraform/plugin/framework) can be found in the [Plugin Development Best Practices](/terraform/plugin/best-practices) section. +This best practices section only contains guidance for plugins built with [Terraform Plugin SDK](/terraform/plugin/sdkv2). More generic best practices that apply to both SDK and [Terraform Plugin Framework](/terraform/plugin/framework) can be found in the [Plugin Development Best Practices](/terraform/plugin/best-practices) section.