Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

account for sql user names that are different for iam users #4984

Merged
merged 3 commits into from
Jul 23, 2021
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions mmv1/third_party/terraform/resources/resource_sql_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ import (
sqladmin "google.golang.org/api/sqladmin/v1beta4"
)

func diffSuppressIamUserName(_, old, new string, d *schema.ResourceData) bool {
strippedName := strings.Split(new, "@")[0]

userType := d.Get("type").(string)

if old == strippedName && strings.Contains(userType, "IAM") {
return true
}

return false
}

func resourceSqlUser() *schema.Resource {
return &schema.Resource{
Create: resourceSqlUserCreate,
Expand All @@ -34,6 +46,7 @@ func resourceSqlUser() *schema.Resource {
"host": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

Does host get automatically set for a MySQL IAM user? What does it get set to?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the example I used it was automatically set to "%". According to our documentation, it's required for MySql, I assume this "%" is IAM specific. I couldn't find much on it though. But I know it means all hosts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, maybe it's not required for mysql. i might be wrong on that. but it did default to this.

ForceNew: true,
Description: `The host the user can connect from. This is only supported for MySQL instances. Don't set this field for PostgreSQL instances. Can be an IP address. Changing this forces a new resource to be created.`,
},
Expand All @@ -46,10 +59,11 @@ func resourceSqlUser() *schema.Resource {
},

"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `The name of the user. Changing this forces a new resource to be created.`,
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: diffSuppressIamUserName,
Description: `The name of the user. Changing this forces a new resource to be created.`,
},

"password": {
Expand Down Expand Up @@ -173,10 +187,13 @@ func resourceSqlUserRead(d *schema.ResourceData, meta interface{}) error {

var user *sqladmin.User
for _, currentUser := range users.Items {

name = strings.Split(name, "@")[0]

if currentUser.Name == name {
// Host can only be empty for postgres instances,
// so don't compare the host if the API host is empty.
if currentUser.Host == "" || currentUser.Host == host {
if host == "" || currentUser.Host == host {
user = currentUser
break
}
Expand Down
88 changes: 88 additions & 0 deletions mmv1/third_party/terraform/tests/resource_sql_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,33 @@ func TestAccSqlUser_mysql(t *testing.T) {
})
}

func TestAccSqlUser_iamUser(t *testing.T) {
// Multiple fine-grained resources
skipIfVcr(t)
t.Parallel()

instance := fmt.Sprintf("i-%d", randInt(t))
vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccSqlUserDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testGoogleSqlUser_iamUser(instance),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"),
),
},
{
ResourceName: "google_sql_user.user1",
ImportStateId: fmt.Sprintf("%s/%s/gmail.com/admin", getTestProjectFromEnv(), instance),
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccSqlUser_postgres(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -201,6 +228,10 @@ func testAccSqlUserDestroyProducer(t *testing.T) func(s *terraform.State) error
users, err := config.NewSqlAdminClient(config.userAgent).Users.List(config.Project,
instance).Do()

if users == nil {
return nil
}

for _, user := range users.Items {
if user.Name == name && user.Host == host {
return fmt.Errorf("User still %s exists %s", name, err)
Expand Down Expand Up @@ -323,3 +354,60 @@ resource "google_sql_database_instance" "instance" {
}
`, instance)
}

func testGoogleSqlUser_iamUser(instance string) string {
return fmt.Sprintf(`
resource "google_sql_database_instance" "instance" {
database_version = "MYSQL_8_0"
name = "%s"
region = "us-central1"

settings {
tier = "db-f1-micro"
availability_type = "REGIONAL"

backup_configuration {
enabled = true
binary_log_enabled = true
}

database_flags {
name = "cloudsql_iam_authentication"
value = "on"
}
}

deletion_protection = false
}

resource "google_sql_database" "db" {
name = "%s"
instance = google_sql_database_instance.instance.name
}

resource "google_service_account" "sa" {
account_id = "%s"
display_name = "%s"
}

resource "google_service_account_key" "sa_key" {
service_account_id = google_service_account.sa.email
}

resource "google_sql_user" "user1" {
name = google_service_account.sa.email
instance = google_sql_database_instance.instance.name
type = "CLOUD_IAM_SERVICE_ACCOUNT"
}

resource "google_project_iam_member" "instance_user" {
role = "roles/cloudsql.instanceUser"
member = "serviceAccount:${google_service_account.sa.email}"
}

resource "google_project_iam_member" "sa_user" {
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${google_service_account.sa.email}"
}
`, instance, instance, instance, instance)
}