Skip to content

Commit 194eb2f

Browse files
Add support for abandoning sql user (#4231) (#2719)
* Add support for abandoning sql user * Update docs * PR feedback Signed-off-by: Modular Magician <[email protected]>
1 parent d614a98 commit 194eb2f

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

.changelog/4231.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
sql: added `deletion_policy` field to `google_sql_user` to enable abandoning users rather than deleting them
3+
```

google-beta/resource_sql_user.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"time"
88

99
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1011
sqladmin "google.golang.org/api/sqladmin/v1beta4"
1112
)
1213

@@ -65,6 +66,15 @@ func resourceSqlUser() *schema.Resource {
6566
ForceNew: true,
6667
Description: `The ID of the project in which the resource belongs. If it is not provided, the provider project is used.`,
6768
},
69+
70+
"deletion_policy": {
71+
Type: schema.TypeString,
72+
Optional: true,
73+
Description: `The deletion policy for the user. Setting ABANDON allows the resource
74+
to be abandoned rather than deleted. This is useful for Postgres, where users cannot be deleted from the API if they
75+
have been granted SQL roles. Possible values are: "ABANDON".`,
76+
ValidateFunc: validation.StringInSlice([]string{"ABANDON", ""}, false),
77+
},
6878
},
6979
}
7080
}
@@ -236,6 +246,13 @@ func resourceSqlUserUpdate(d *schema.ResourceData, meta interface{}) error {
236246

237247
func resourceSqlUserDelete(d *schema.ResourceData, meta interface{}) error {
238248
config := meta.(*Config)
249+
250+
if deletionPolicy := d.Get("deletion_policy"); deletionPolicy == "ABANDON" {
251+
// Allows for user to be abandoned without deletion to avoid deletion failing
252+
// for Postgres users in some circumstances due to existing SQL roles
253+
return nil
254+
}
255+
239256
userAgent, err := generateUserAgentString(d, config.userAgent)
240257
if err != nil {
241258
return err

google-beta/resource_sql_user_test.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,40 @@ func TestAccSqlUser_postgres(t *testing.T) {
7878
})
7979
}
8080

81+
func TestAccSqlUser_postgresAbandon(t *testing.T) {
82+
t.Parallel()
83+
84+
instance := fmt.Sprintf("i-%d", randInt(t))
85+
userName := "admin"
86+
vcrTest(t, resource.TestCase{
87+
PreCheck: func() { testAccPreCheck(t) },
88+
Providers: testAccProviders,
89+
CheckDestroy: testAccSqlUserDestroyProducer(t),
90+
Steps: []resource.TestStep{
91+
{
92+
Config: testGoogleSqlUser_postgresAbandon(instance, userName),
93+
Check: resource.ComposeTestCheckFunc(
94+
testAccCheckGoogleSqlUserExists(t, "google_sql_user.user"),
95+
),
96+
},
97+
{
98+
ResourceName: "google_sql_user.user",
99+
ImportStateId: fmt.Sprintf("%s/%s/admin", getTestProjectFromEnv(), instance),
100+
ImportState: true,
101+
ImportStateVerify: true,
102+
ImportStateVerifyIgnore: []string{"password", "deletion_policy"},
103+
},
104+
{
105+
// Abandon user
106+
Config: testGoogleSqlUser_postgresNoUser(instance),
107+
Check: resource.ComposeTestCheckFunc(
108+
testAccCheckGoogleSqlUserExistsWithName(t, instance, userName),
109+
),
110+
},
111+
},
112+
})
113+
}
114+
81115
func testAccCheckGoogleSqlUserExists(t *testing.T, n string) resource.TestCheckFunc {
82116
return func(s *terraform.State) error {
83117
config := googleProviderConfig(t)
@@ -106,6 +140,27 @@ func testAccCheckGoogleSqlUserExists(t *testing.T, n string) resource.TestCheckF
106140
}
107141
}
108142

143+
func testAccCheckGoogleSqlUserExistsWithName(t *testing.T, instance, name string) resource.TestCheckFunc {
144+
return func(s *terraform.State) error {
145+
config := googleProviderConfig(t)
146+
147+
users, err := config.NewSqlAdminClient(config.userAgent).Users.List(config.Project,
148+
instance).Do()
149+
150+
if err != nil {
151+
return err
152+
}
153+
154+
for _, user := range users.Items {
155+
if user.Name == name {
156+
return nil
157+
}
158+
}
159+
160+
return fmt.Errorf("Not found: User: %s in instance: %s: %s", name, instance, err)
161+
}
162+
}
163+
109164
func testAccSqlUserDestroyProducer(t *testing.T) func(s *terraform.State) error {
110165
return func(s *terraform.State) error {
111166
for _, rs := range s.RootModule().Resources {
@@ -180,3 +235,40 @@ resource "google_sql_user" "user" {
180235
}
181236
`, instance, password)
182237
}
238+
239+
func testGoogleSqlUser_postgresAbandon(instance, name string) string {
240+
return fmt.Sprintf(`
241+
resource "google_sql_database_instance" "instance" {
242+
name = "%s"
243+
region = "us-central1"
244+
database_version = "POSTGRES_9_6"
245+
deletion_protection = false
246+
247+
settings {
248+
tier = "db-f1-micro"
249+
}
250+
}
251+
252+
resource "google_sql_user" "user" {
253+
name = "%s"
254+
instance = google_sql_database_instance.instance.name
255+
password = "password"
256+
deletion_policy = "ABANDON"
257+
}
258+
`, instance, name)
259+
}
260+
261+
func testGoogleSqlUser_postgresNoUser(instance string) string {
262+
return fmt.Sprintf(`
263+
resource "google_sql_database_instance" "instance" {
264+
name = "%s"
265+
region = "us-central1"
266+
database_version = "POSTGRES_9_6"
267+
deletion_protection = false
268+
269+
settings {
270+
tier = "db-f1-micro"
271+
}
272+
}
273+
`, instance)
274+
}

website/docs/r/sql_user.html.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ The following arguments are supported:
5353
* `password` - (Optional) The password for the user. Can be updated. For Postgres
5454
instances this is a Required field.
5555

56+
* `deletion_policy` - (Optional) The deletion policy for the user.
57+
Setting `ABANDON` allows the resource to be abandoned rather than deleted. This is useful
58+
for Postgres, where users cannot be deleted from the API if they have been granted SQL roles.
59+
60+
Possible values are: `ABANDON`.
61+
5662
- - -
5763

5864
* `host` - (Optional) The host the user can connect from. This is only supported

0 commit comments

Comments
 (0)