Skip to content

Commit 427d866

Browse files
akemner-figmaclaude
andcommitted
group_settings: remove from state on 404 instead of erroring during read
When the underlying group is deleted outside Terraform, resourceGroupSettingsRead returned the 404 as a fatal error, so plan/refresh failed and the resource was never dropped from state — the only recovery was a manual `terraform state rm`. Route the group Get 404 through handleNotFoundError (which does d.SetId("")), matching the existing behavior of resource_group. Non-404 errors are unchanged. Adds TestAccResourceGroupSettings_disappears covering out-of-band group deletion. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2913724 commit 427d866

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

internal/provider/resource_group_settings.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,9 @@ func resourceGroupSettingsRead(ctx context.Context, d *schema.ResourceData, meta
472472

473473
group, err := groupsService.Get(d.Id()).Do()
474474
if err != nil {
475-
return diag.FromErr(err)
475+
// If the underlying group is gone, drop the settings from state instead
476+
// of erroring on the 404, matching resource_group's behavior.
477+
return handleNotFoundError(err, d, d.Get("email").(string))
476478
}
477479

478480
// Convert strings to bools

internal/provider/resource_group_settings_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1314
)
1415

1516
func TestAccResourceGroupSettings_basic(t *testing.T) {
@@ -42,6 +43,76 @@ func TestAccResourceGroupSettings_basic(t *testing.T) {
4243
})
4344
}
4445

46+
// TestAccResourceGroupSettings_disappears verifies that when the underlying
47+
// group is deleted outside Terraform, the group_settings resource is dropped
48+
// from state on the next refresh instead of failing the plan on a 404.
49+
func TestAccResourceGroupSettings_disappears(t *testing.T) {
50+
t.Parallel()
51+
52+
domainName := os.Getenv("GOOGLEWORKSPACE_DOMAIN")
53+
54+
if domainName == "" {
55+
t.Skip("GOOGLEWORKSPACE_DOMAIN needs to be set to run this test")
56+
}
57+
58+
testGroupVals := map[string]interface{}{
59+
"domainName": domainName,
60+
"email": fmt.Sprintf("tf-test-%s", acctest.RandString(10)),
61+
}
62+
63+
resource.Test(t, resource.TestCase{
64+
PreCheck: func() { testAccPreCheck(t) },
65+
ProviderFactories: providerFactories,
66+
Steps: []resource.TestStep{
67+
{
68+
Config: testAccResourceGroupSettings_basic(testGroupVals),
69+
},
70+
{
71+
// Delete the group outside Terraform. On refresh, group_settings
72+
// must self-heal (remove from state) and plan to recreate,
73+
// instead of erroring on the 404.
74+
Config: testAccResourceGroupSettings_basic(testGroupVals),
75+
Check: resource.ComposeTestCheckFunc(
76+
testAccDeleteGroupOutOfBand("googleworkspace_group.my-group"),
77+
),
78+
ExpectNonEmptyPlan: true,
79+
},
80+
},
81+
})
82+
}
83+
84+
// testAccDeleteGroupOutOfBand deletes the referenced group directly via the API,
85+
// simulating the group being removed outside Terraform.
86+
func testAccDeleteGroupOutOfBand(resourceName string) resource.TestCheckFunc {
87+
return func(s *terraform.State) error {
88+
rs, ok := s.RootModule().Resources[resourceName]
89+
if !ok {
90+
return fmt.Errorf("%s key not found in state", resourceName)
91+
}
92+
93+
client, err := googleworkspaceTestClient()
94+
if err != nil {
95+
return err
96+
}
97+
98+
directoryService, diags := client.NewDirectoryService()
99+
if diags.HasError() {
100+
return fmt.Errorf("error creating directory service %+v", diags)
101+
}
102+
103+
groupsService, diags := GetGroupsService(directoryService)
104+
if diags.HasError() {
105+
return fmt.Errorf("error getting groups service %+v", diags)
106+
}
107+
108+
if err := groupsService.Delete(rs.Primary.ID).Do(); err != nil {
109+
return fmt.Errorf("error deleting group out of band (%s): %w", rs.Primary.ID, err)
110+
}
111+
112+
return nil
113+
}
114+
}
115+
45116
func TestAccResourceGroupSettings_full(t *testing.T) {
46117
t.Parallel()
47118

0 commit comments

Comments
 (0)