Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/content/best-practices/deletion-behaviors.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ weight: 20
---

# Deletion behaviors
> [!NOTE]
> **Note:** The guidance on this page has largely been superceded by the implementation of [Universal Deletion Policy]({{< ref "/reference/universal-deletion-policy" >}}). Please refer to that page for details on how to modify the standard implementation of these fields going forward. Any new specifically `deletion_protection` fields should be handled on a case by case basis.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

rather than having this comment, we should remove this page (or merge it with the deletion policy page as discussed in another comment)


> [!NOTE]
> **Note:** This page covers best practices guidance for the Terraform provider for Google Cloud, which is used to ensure a consistent UX for Terraform users across providers or GCP users across the Google provider. Generally, this guidance should be followed and exceptions should be clearly demarcated / discussed.
Expand All @@ -21,8 +23,6 @@ If the API has a deletion protection field, the corresponding Terraform field na

A resource can have up to two `deletion_protection` fields (with different names): one that represents a field in the API, and one that is only in Terraform. This could happen because the API added its field after `deletion_protection` already existed in Terraform; it could also happen because a separate field was added in Terraform to make sure that `deletion_protection` is enabled by default. In either case, they should be reconciled into a single field (that defaults to enabled and whose name matches the API field) in the next major release.

Resources that do not have a significant risk of unrecoverable data loss or similar critical concern will not be given `deletion_protection` fields.

See [Client-side fields]({{< ref "/develop/client-side-fields" >}}) for information about adding `deletion_protection` fields.

> [!NOTE]
Expand Down
6 changes: 2 additions & 4 deletions docs/content/develop/client-side-fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ weight: 150

Client-side fields are most often used as flags to modify the behavior of a Terraform resource. Because they don't correspond to an API field, there are some additional considerations in terms of how to implement them.

Common client-side fields include:

- [`deletion_protection`]({{< ref "/best-practices/deletion-behaviors#deletion_protection" >}})
- [`deletion_policy`]({{< ref "/best-practices/deletion-behaviors#deletion_policy" >}})
> [!NOTE]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

rather than have this comment, could we rewrite the examples to be something other than deletion_protection + add a note about deletion_policy fields linking to those docs (assuming they're a separate page)

> **Note:** Examples here detail the implementation of a `deletion_protection` field, previously one of the common usages of client-side fields. Direct implementation of `deletion_protection` and `deletion_policy` fields has been largely superceded by [Universal Deletion Policy]({{< ref "/reference/universal-deletion-policy" >}}). Please refer to that page for details on how to handle those specific fields going forward. The guidance here is still an accurate example of how to implement other kinds of client-side fields.

{{% tabs "schema" %}}
{{< tab "MMv1" >}}
Expand Down
125 changes: 125 additions & 0 deletions docs/content/reference/universal-deletion-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
title: "Universal Deletion Policy"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd recommend removing references to "Universal" here & elsewhere (including the filename) - although it's the name of the project, it's probably not important to contributors.

Additionally - this page probably shouldn't be in reference, since it's not a reference - it should either go in develop or best-practices. Personally I'd lean towards replacing best-practices/deletion-behaviors with this content. You don't need to keep that page name, but make sure to add an alias so that references to the old location will redirect.

You'll also want to update the MMv1 resource reference to include the new YAML fields in a reference format (similar to the way other YAML fields are documented on that page.)

weight: 20
---
Almost all resources in the provider now support a universal `deletion_policy` field, superceding previous guidance on implementing `deletion_protection` or unique `deletion_policy` fields from [Deletion behaviors]({{< ref "/best-practices/deletion-behaviors" >}}).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

here and elsewhere: I'd recommend just capturing the current state; we don't need to refer to the previous guidance - or if we do, it should be deprioritized (for example, at the end this page, you could have a "Legacy deletion behaviors" section that summarizes the important points that people need to know for maintaining older fields on resources.)


This page documents how to work with the universal deletion policy in either generated or handwritten resources.

{{% tabs "schema" %}}
{{< tab "MMv1" >}}
By default, existing and new resources should support `deletion_policy` without any complication or changes needed by a contributor. A handful of options are available to customize the implementation as necessary.

##Updating the default value of `deletion_policy` for a resource
All resources will use a value of "DELETE" by default if unspecified, but this default can be changed to another value by including the following:
```yaml
deletion_policy_default: "PREVENT" #this can be any string
```
This is how resources should be modified for implementing default deletion protection guards going forward.

##Supporting a custom value for deletion_policy
If implementing support for additional values such as "FORCE", the following steps can be taken.
A `pre_delete` constant should be added to the `custom_code` block in the resource YAML file, that performs the logic with the corresponding value. Example implemention here: [#1](https://github.com/GoogleCloudPlatform/magic-modules/FEATURE-BRANCH-universal-deletion-policy/mmv1/products/datastream/PrivateConnection.yaml#L44), [#2](https://github.com/GoogleCloudPlatform/magic-modules/blob/FEATURE-BRANCH-universal-deletion-policy/mmv1/templates/terraform/pre_delete/private_connection.go.tmpl)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Generally we try to avoid "should": https://developers.google.com/style/prescriptive-documentation#word-choice

I think this might be more clear in active voice as well: https://developers.google.com/style/voice

Suggested change
A `pre_delete` constant should be added to the `custom_code` block in the resource YAML file, that performs the logic with the corresponding value. Example implemention here: [#1](https://github.com/GoogleCloudPlatform/magic-modules/FEATURE-BRANCH-universal-deletion-policy/mmv1/products/datastream/PrivateConnection.yaml#L44), [#2](https://github.com/GoogleCloudPlatform/magic-modules/blob/FEATURE-BRANCH-universal-deletion-policy/mmv1/templates/terraform/pre_delete/private_connection.go.tmpl)
Add a `pre_delete` constant to the `custom_code` block in the resource YAML file that performs the logic with the corresponding value. Example implemention here: [#1](https://github.com/GoogleCloudPlatform/magic-modules/FEATURE-BRANCH-universal-deletion-policy/mmv1/products/datastream/PrivateConnection.yaml#L44), [#2](https://github.com/GoogleCloudPlatform/magic-modules/blob/FEATURE-BRANCH-universal-deletion-policy/mmv1/templates/terraform/pre_delete/private_connection.go.tmpl)

Also relevant: https://developers.google.com/style/procedures

This should also be changed in the preceding & following sentences, and maybe elsewhere.


Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe it's obvious, but it's important that custom deletion policies should be specifically tested. Since the expectation is that the non-custom ones won't be usually.

In the resource YAML, the following also should be included so documentation can be provided to explain the custom values.
```yaml
deletion_policy_custom_docs: true
```
This attribute will prevent the default universal deletion policy field documentation from being generated. A custom field description can instead be generated by adding a virtual field with the `exclude: true` attribute set, similar to the following, to the resource YAML file.
```yaml
virtual_fields:
- name: 'deletion_policy'
description: |
The deletion policy for the private connection. Setting `FORCE` will also delete any child
routes that belong to this private connection. Setting `DEFAULT` will fail the delete if
child routes exist. Defaults to `FORCE` for backwards compatibility.

When a 'terraform destroy' or 'terraform apply' would delete the resource,
the command will fail if this field is set to "PREVENT" in Terraform state.
When set to "ABANDON", the command will remove the resource from Terraform
management without updating or deleting the resource in the API.
When set to "DELETE", the command will behave as if set to "DEFAULT".
type: String
exclude: true
```

##Excluding a resource from universal deletion_policy
If a resource is incompatible with `deletion_policy` the following can be added to the resource YAML file, and all related code will not be generated:
```yaml
deletion_policy_exclude: true
```
{{< /tab >}}
{{< tab "Handwritten" >}}
All handwritten resources need to support `deletion_policy` unless deemed incompatible. The following code snippets need to be included in a resource to support this. If following steps under [Add Resource]({{< ref "/develop/add-resource/#handwritten" >}}), they should be included in your resource go file already.

###CustomizeDiff
The `tpgresource.DefaultProviderDeletionPolicy()` should be added to the CustomDiff attribute of a given resource's `*schema.Resource`. If no existing CustomizeDiff is present, the whole attribute should be added.
```go
CustomizeDiff: customdiff.All(
tpgresource.DefaultProviderDeletionPolicy("DELETE"),
),
```
If the default is being changed, it should also be updated from "DELETE" here.

###Schema
The following should be added to the top level schema of the resource:
```go
"deletion_policy": tpgresource.DeletionPolicySchemaEntry("DELETE"),
```
If the default is being changed, it should also be updated from "DELETE" here.

###Read
The following should be added to the end of a resource's Read() function:
```go
if err := tpgresource.DeletionPolicyReadDefault(d, config, "DELETE"); err != nil {
return err
}
```
If the default is being changed, it should also be updated from "DELETE" here.

###Update
The following should be added to the start of a resource's Update() function:
```go
if tpgresource.DeletionPolicyPreUpdate(d, RESOURCENAME) {
return RESOURCENAME().Read(d, meta)
}
```
If the resource does not support updating, the following entire Update() function should be added:
```go
//UDP update start
func resourceRESOURCENAMEUpdate(d *schema.ResourceData, meta interface{}) error {
// Only the root field "deletion_policy", "labels", "terraform_labels", and virtual fields are mutable
return resourceRESOURCENAMERead(d, meta)
}
//UDP update end
```

###Delete
The following should be added to the start of a resource's Delete() function, or modified depending on what custom values are supported:
```go
if ok, err := tpgresource.DeletionPolicyPreDelete(d); err != nil{
return err
}else if ok{
return nil
}
```

###Metadata
The following line should be added to a resource's meta.yaml:
```yaml
- field: 'deletion_policy'
provider_only: true
```

###Docs
The following should be added to a resource's documentation markdown file, or modified depending on what custom values are supported:
```markdown
* `deletion_policy` - (Optional) Whether Terraform will be prevented from destroying the resource. Defaults to "DELETE".
When a 'terraform destroy' or 'terraform apply' would delete the resource,
the command will fail if this field is set to "PREVENT" in Terraform state.
When set to "ABANDON", the command will remove the resource from Terraform
management without updating or deleting the resource in the API.
When set to "DELETE", deleting the resource is allowed.
```
{{< /tab >}}
{{% /tabs %}}
Loading