Skip to content
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .changelog/17380.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
provider: support for a `deletion_policy` field has been added to almost all resources in the provider. Details on its usage can be found within individual resource documentation if supported.
```
2 changes: 1 addition & 1 deletion google/acctest/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func CheckDataSourceStateMatchesResourceStateWithIgnores(dataSourceName, resourc
continue
}

if strings.HasPrefix(k, "labels.") || strings.HasPrefix(k, "terraform_labels.") || strings.HasPrefix(k, "effective_labels.") {
if strings.HasPrefix(k, "labels.") || strings.HasPrefix(k, "terraform_labels.") || strings.HasPrefix(k, "effective_labels.") || strings.HasPrefix(k, "deletion_policy") {
continue
}
if k == "%" {
Expand Down
5 changes: 5 additions & 0 deletions google/acctest/vcr_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ func VcrTest(t *testing.T, c resource.TestCase) {
re := regexp.MustCompile(`create_duration = "\d+[sm]"`)
s.Config = re.ReplaceAllString(s.Config, `create_duration = "1s"`)
}
// deletion_policy is a universal virtual attribute for managing the behavior of resources when a delete is attempted
// in Terraform. Because it is a virtual attribute, it needs to be excluded from these ImportStateVerifys.
if s.ImportStateVerify && !slices.Contains(s.ImportStateVerifyIgnore, "deletion_policy") {
s.ImportStateVerifyIgnore = append(s.ImportStateVerifyIgnore, "deletion_policy")
}
steps = append(steps, s)
}
c.Steps = steps
Expand Down
1 change: 1 addition & 0 deletions google/fwmodels/provider_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type ProviderModel struct {
RequestTimeout types.String `tfsdk:"request_timeout"`
RequestReason types.String `tfsdk:"request_reason"`
PollInterval types.String `tfsdk:"poll_interval"`
DeletionPolicy types.String `tfsdk:"deletion_policy"`
UniverseDomain types.String `tfsdk:"universe_domain"`
DefaultLabels types.Map `tfsdk:"default_labels"`
AddTerraformAttributionLabel types.Bool `tfsdk:"add_terraform_attribution_label"`
Expand Down
3 changes: 3 additions & 0 deletions google/fwprovider/framework_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest,
fwvalidators.NonNegativeDurationValidator(),
},
},
"deletion_policy": schema.StringAttribute{
Optional: true,
},
"request_reason": schema.StringAttribute{
Optional: true,
},
Expand Down
9 changes: 9 additions & 0 deletions google/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ func Provider() *schema.Provider {
Optional: true,
},

"deletion_policy": {
Type: schema.TypeString,
Optional: true,
},

"request_reason": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -292,6 +297,10 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr
}
}

if v, ok := d.GetOk("deletion_policy"); ok {
config.DeletionPolicy = v.(string)
}

if v, ok := d.GetOk("request_reason"); ok {
config.RequestReason = v.(string)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,19 @@ as key versions are inherited top-down.`,
Computed: true,
Description: `The resource name of the settings. Format is "folders/{folder_id}/accessApprovalSettings"`,
},

"deletion_policy": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: `Whether Terraform will be prevented from destroying the instance. Defaults to "DELETE".
When a 'terraform destroy' or 'terraform apply' would delete the instance,
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.
`,
},
},
UseJSONNumber: true,
}
Expand Down Expand Up @@ -396,6 +409,20 @@ func resourceAccessApprovalFolderSettingsRead(d *schema.ResourceData, meta inter

log.Printf("[DEBUG] Finished reading AccessApprovalFolderSettings %q: %#v", d.Id(), res)

// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOkExists("deletion_policy"); !ok {
//prioritize config's value if present
if config.DeletionPolicy != "" {
if err := d.Set("deletion_policy", config.DeletionPolicy); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
} else {
if err := d.Set("deletion_policy", "DELETE"); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
}
}

err = ResourceAccessApprovalFolderSettingsFlatten(d, meta, res, config, userAgent, billingProject, url, headers)
if err != nil {
return err
Expand All @@ -417,6 +444,19 @@ func resourceAccessApprovalFolderSettingsRead(d *schema.ResourceData, meta inter
}

func resourceAccessApprovalFolderSettingsUpdate(d *schema.ResourceData, meta interface{}) error {
clientSideFields := map[string]bool{"deletion_policy": true}
clientSideOnly := true
for field := range ResourceAccessApprovalFolderSettings().Schema {
if d.HasChange(field) && !clientSideFields[field] {
clientSideOnly = false
break
}
}
if clientSideOnly {
log.Print("[DEBUG] Only client-side changes detected. Cancelling update operation.")
return resourceAccessApprovalFolderSettingsRead(d, meta)
}

config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down Expand Up @@ -516,6 +556,13 @@ func resourceAccessApprovalFolderSettingsUpdate(d *schema.ResourceData, meta int
}

func resourceAccessApprovalFolderSettingsDelete(d *schema.ResourceData, meta interface{}) error {
if d.Get("deletion_policy").(string) == "PREVENT" {
return fmt.Errorf("cannot destroy AccessApprovalFolderSettings without setting deletion_policy=\"DELETE\" and running `terraform apply`")
}
if d.Get("deletion_policy").(string) == "ABANDON" {
log.Printf("[DEBUG] deletion_policy set to \"ABANDON\", removing FolderSettings %q from Terraform state without deletion", d.Id())
return nil
}
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ fields:
- api_field: invalidKeyVersion
- api_field: name
- api_field: notificationEmails
- field: deletion_policy
provider_only: true
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,19 @@ correct permissions on it, etc.).`,
Computed: true,
Description: `The resource name of the settings. Format is "organizations/{organization_id}/accessApprovalSettings"`,
},

"deletion_policy": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: `Whether Terraform will be prevented from destroying the instance. Defaults to "DELETE".
When a 'terraform destroy' or 'terraform apply' would delete the instance,
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.
`,
},
},
UseJSONNumber: true,
}
Expand Down Expand Up @@ -357,6 +370,20 @@ func resourceAccessApprovalOrganizationSettingsRead(d *schema.ResourceData, meta

log.Printf("[DEBUG] Finished reading AccessApprovalOrganizationSettings %q: %#v", d.Id(), res)

// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOkExists("deletion_policy"); !ok {
//prioritize config's value if present
if config.DeletionPolicy != "" {
if err := d.Set("deletion_policy", config.DeletionPolicy); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
} else {
if err := d.Set("deletion_policy", "DELETE"); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
}
}

err = ResourceAccessApprovalOrganizationSettingsFlatten(d, meta, res, config, userAgent, billingProject, url, headers)
if err != nil {
return err
Expand All @@ -378,6 +405,19 @@ func resourceAccessApprovalOrganizationSettingsRead(d *schema.ResourceData, meta
}

func resourceAccessApprovalOrganizationSettingsUpdate(d *schema.ResourceData, meta interface{}) error {
clientSideFields := map[string]bool{"deletion_policy": true}
clientSideOnly := true
for field := range ResourceAccessApprovalOrganizationSettings().Schema {
if d.HasChange(field) && !clientSideFields[field] {
clientSideOnly = false
break
}
}
if clientSideOnly {
log.Print("[DEBUG] Only client-side changes detected. Cancelling update operation.")
return resourceAccessApprovalOrganizationSettingsRead(d, meta)
}

config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down Expand Up @@ -477,6 +517,13 @@ func resourceAccessApprovalOrganizationSettingsUpdate(d *schema.ResourceData, me
}

func resourceAccessApprovalOrganizationSettingsDelete(d *schema.ResourceData, meta interface{}) error {
if d.Get("deletion_policy").(string) == "PREVENT" {
return fmt.Errorf("cannot destroy AccessApprovalOrganizationSettings without setting deletion_policy=\"DELETE\" and running `terraform apply`")
}
if d.Get("deletion_policy").(string) == "ABANDON" {
log.Printf("[DEBUG] deletion_policy set to \"ABANDON\", removing OrganizationSettings %q from Terraform state without deletion", d.Id())
return nil
}
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ fields:
- api_field: notificationEmails
- field: organization_id
provider_only: true
- field: deletion_policy
provider_only: true
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,19 @@ as key versions are inherited top-down.`,
Computed: true,
Description: `The resource name of the settings. Format is "projects/{project_id}/accessApprovalSettings"`,
},

"deletion_policy": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: `Whether Terraform will be prevented from destroying the instance. Defaults to "DELETE".
When a 'terraform destroy' or 'terraform apply' would delete the instance,
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.
`,
},
},
UseJSONNumber: true,
}
Expand Down Expand Up @@ -375,6 +388,20 @@ func resourceAccessApprovalProjectSettingsRead(d *schema.ResourceData, meta inte

log.Printf("[DEBUG] Finished reading AccessApprovalProjectSettings %q: %#v", d.Id(), res)

// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOkExists("deletion_policy"); !ok {
//prioritize config's value if present
if config.DeletionPolicy != "" {
if err := d.Set("deletion_policy", config.DeletionPolicy); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
} else {
if err := d.Set("deletion_policy", "DELETE"); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
}
}

err = ResourceAccessApprovalProjectSettingsFlatten(d, meta, res, config, userAgent, billingProject, url, headers)
if err != nil {
return err
Expand All @@ -396,6 +423,19 @@ func resourceAccessApprovalProjectSettingsRead(d *schema.ResourceData, meta inte
}

func resourceAccessApprovalProjectSettingsUpdate(d *schema.ResourceData, meta interface{}) error {
clientSideFields := map[string]bool{"deletion_policy": true}
clientSideOnly := true
for field := range ResourceAccessApprovalProjectSettings().Schema {
if d.HasChange(field) && !clientSideFields[field] {
clientSideOnly = false
break
}
}
if clientSideOnly {
log.Print("[DEBUG] Only client-side changes detected. Cancelling update operation.")
return resourceAccessApprovalProjectSettingsRead(d, meta)
}

config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down Expand Up @@ -505,6 +545,13 @@ func resourceAccessApprovalProjectSettingsUpdate(d *schema.ResourceData, meta in
}

func resourceAccessApprovalProjectSettingsDelete(d *schema.ResourceData, meta interface{}) error {
if d.Get("deletion_policy").(string) == "PREVENT" {
return fmt.Errorf("cannot destroy AccessApprovalProjectSettings without setting deletion_policy=\"DELETE\" and running `terraform apply`")
}
if d.Get("deletion_policy").(string) == "ABANDON" {
log.Printf("[DEBUG] deletion_policy set to \"ABANDON\", removing ProjectSettings %q from Terraform state without deletion", d.Id())
return nil
}
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ fields:
- api_field: project
- field: project_id
provider_only: true
- field: deletion_policy
provider_only: true
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,19 @@ custom access levels - https://cloud.google.com/access-context-manager/docs/cust
Optional: true,
Description: `Description of the AccessLevel and its use. Does not affect behavior.`,
},

"deletion_policy": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: `Whether Terraform will be prevented from destroying the instance. Defaults to "DELETE".
When a 'terraform destroy' or 'terraform apply' would delete the instance,
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.
`,
},
},
UseJSONNumber: true,
}
Expand Down Expand Up @@ -556,6 +569,20 @@ func resourceAccessContextManagerAccessLevelRead(d *schema.ResourceData, meta in

log.Printf("[DEBUG] Finished reading AccessContextManagerAccessLevel %q: %#v", d.Id(), res)

// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOkExists("deletion_policy"); !ok {
//prioritize config's value if present
if config.DeletionPolicy != "" {
if err := d.Set("deletion_policy", config.DeletionPolicy); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
} else {
if err := d.Set("deletion_policy", "DELETE"); err != nil {
return fmt.Errorf("Error setting deletion_policy: %s", err)
}
}
}

err = ResourceAccessContextManagerAccessLevelFlatten(d, meta, res, config, userAgent, billingProject, url, headers)
if err != nil {
return err
Expand All @@ -577,6 +604,19 @@ func resourceAccessContextManagerAccessLevelRead(d *schema.ResourceData, meta in
}

func resourceAccessContextManagerAccessLevelUpdate(d *schema.ResourceData, meta interface{}) error {
clientSideFields := map[string]bool{"deletion_policy": true}
clientSideOnly := true
for field := range ResourceAccessContextManagerAccessLevel().Schema {
if d.HasChange(field) && !clientSideFields[field] {
clientSideOnly = false
break
}
}
if clientSideOnly {
log.Print("[DEBUG] Only client-side changes detected. Cancelling update operation.")
return resourceAccessContextManagerAccessLevelRead(d, meta)
}

config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down Expand Up @@ -701,6 +741,13 @@ func resourceAccessContextManagerAccessLevelUpdate(d *schema.ResourceData, meta
}

func resourceAccessContextManagerAccessLevelDelete(d *schema.ResourceData, meta interface{}) error {
if d.Get("deletion_policy").(string) == "PREVENT" {
return fmt.Errorf("cannot destroy AccessContextManagerAccessLevel without setting deletion_policy=\"DELETE\" and running `terraform apply`")
}
if d.Get("deletion_policy").(string) == "ABANDON" {
log.Printf("[DEBUG] deletion_policy set to \"ABANDON\", removing AccessLevel %q from Terraform state without deletion", d.Id())
return nil
}
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
Expand Down
Loading
Loading