Skip to content
This repository has been archived by the owner on Oct 11, 2022. It is now read-only.

Commit

Permalink
mysql_grant: Fix the read of grant option.
Browse files Browse the repository at this point in the history
If multiple `mysql_grant` are defined for the same user,
the grant value of the last one will be set for all of them.

The example (that I used in the acceptance tests) to reproduce this bug:

```hcl
terraform {
  required_providers {
    mysql = {
      source = "winebarrel/mysql"
    }
  }
}

resource "mysql_database" "db1" {
  name = "db1"
}

resource "mysql_database" "db2" {
  name = "db2"
}

resource "mysql_user" "test" {
  user = "test"
  host = "%"
}

resource "mysql_grant" "test_db1" {
  user       = mysql_user.test.user
  host       = mysql_user.test.host
  database   = mysql_database.db1.name
  privileges = ["SELECT"]
}

resource "mysql_grant" "test_db2" {
  user       = mysql_user.test.user
  host       = mysql_user.test.host
  database   = mysql_database.db2.name
  privileges = ["SELECT"]
  grant      = true
}
```

After the first apply of these resources, there will be a dirty plan:

```bash
●examples❯ terraform apply -auto-approve
[...]
mysql_database.db2: Creating...
mysql_user.test: Creating...
mysql_database.db1: Creating...
mysql_user.test: Creation complete after 0s [id=test@%]
mysql_database.db1: Creation complete after 0s [id=db1]
mysql_database.db2: Creation complete after 0s [id=db2]
mysql_grant.test_db1: Creating...
mysql_grant.test_db2: Creating...
mysql_grant.test_db2: Creation complete after 0s [id=test@%:`db2`]
mysql_grant.test_db1: Creation complete after 0s [id=test@%:`db1`]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

●examples❯ terraform plan
mysql_user.test: Refreshing state... [id=test@%]
mysql_database.db1: Refreshing state... [id=db1]
mysql_database.db2: Refreshing state... [id=db2]
mysql_grant.test_db2: Refreshing state... [id=test@%:`db2`]
mysql_grant.test_db1: Refreshing state... [id=test@%:`db1`]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # mysql_grant.test_db1 must be replaced
-/+ resource "mysql_grant" "test_db1" {
      ~ grant      = true -> false # forces replacement
      ~ id         = "test@%:`db1`" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.
```
  • Loading branch information
cyrilgdn committed Jul 28, 2021
1 parent 218109d commit 0a47158
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
8 changes: 4 additions & 4 deletions mysql/resource_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,10 @@ func ReadGrant(d *schema.ResourceData, meta interface{}) error {
for _, grant := range grants {
if grant.Database == database && grant.Table == table {
privileges = grant.Privileges
}

if grant.Grant {
grantOption = true
if grant.Grant {
grantOption = true
}
break
}
}

Expand Down
61 changes: 61 additions & 0 deletions mysql/resource_grant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,67 @@ func TestAccGrant(t *testing.T) {
})
}

func TestAccGrant_grantOption(t *testing.T) {
randInt := rand.Intn(100)
db1 := fmt.Sprintf("tf-test-%d", randInt)
db2 := fmt.Sprintf("tf-test-%d", randInt+1)

config := fmt.Sprintf(`
resource "mysql_database" "db1" {
name = "%s"
}
resource "mysql_database" "db2" {
name = "%s"
}
resource "mysql_user" "test" {
user = "jdoe-%d"
host = "example.com"
}
resource "mysql_grant" "test_db1" {
user = mysql_user.test.user
host = mysql_user.test.host
database = mysql_database.db1.name
privileges = ["SELECT"]
}
resource "mysql_grant" "test_db2" {
user = mysql_user.test.user
host = mysql_user.test.host
database = mysql_database.db2.name
privileges = ["SELECT"]
grant = true
}
`, db1, db2, randInt)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccGrantCheckDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccPrivilegeExists("mysql_grant.test_db1", "SELECT"),
resource.TestCheckResourceAttr("mysql_grant.test_db1", "user", fmt.Sprintf("jdoe-%d", randInt)),
resource.TestCheckResourceAttr("mysql_grant.test_db1", "host", "example.com"),
resource.TestCheckResourceAttr("mysql_grant.test_db1", "database", db1),
resource.TestCheckResourceAttr("mysql_grant.test_db1", "table", "*"),
resource.TestCheckResourceAttr("mysql_grant.test_db1", "grant", "false"),

testAccPrivilegeExists("mysql_grant.test_db2", "SELECT"),
resource.TestCheckResourceAttr("mysql_grant.test_db2", "user", fmt.Sprintf("jdoe-%d", randInt)),
resource.TestCheckResourceAttr("mysql_grant.test_db2", "host", "example.com"),
resource.TestCheckResourceAttr("mysql_grant.test_db2", "database", db2),
resource.TestCheckResourceAttr("mysql_grant.test_db2", "grant", "true"),
),
},
},
})
}

func TestAccGrant_role(t *testing.T) {
rand.Seed(time.Now().UnixNano())
dbName := fmt.Sprintf("tf-test-%d", rand.Intn(100))
Expand Down

0 comments on commit 0a47158

Please sign in to comment.