Skip to content

Commit ae587bf

Browse files
author
protomouse
committed
mysql_user pre-5.7.6 compat (hashicorpGH-8230)
1 parent efd6b99 commit ae587bf

7 files changed

Lines changed: 106 additions & 30 deletions

File tree

builtin/providers/mysql/provider.go

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,23 @@ package mysql
22

33
import (
44
"fmt"
5+
"strconv"
56
"strings"
67

7-
mysqlc "github.com/ziutek/mymysql/thrsafe"
8+
mysqlc "github.com/ziutek/mymysql/mysql"
9+
mysqlts "github.com/ziutek/mymysql/thrsafe"
810

911
"github.com/hashicorp/terraform/helper/schema"
1012
"github.com/hashicorp/terraform/terraform"
1113
)
1214

15+
type providerConfiguration struct {
16+
Conn mysqlc.Conn
17+
VersionMajor uint
18+
VersionMinor uint
19+
VersionPatch uint
20+
}
21+
1322
func Provider() terraform.ResourceProvider {
1423
return &schema.Provider{
1524
Schema: map[string]*schema.Schema{
@@ -69,21 +78,65 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
6978
proto = "unix"
7079
}
7180

72-
// mysqlc is the thread-safe implementation of mymysql, so we can
81+
// mysqlts is the thread-safe implementation of mymysql, so we can
7382
// safely re-use the same connection between multiple parallel
7483
// operations.
75-
conn := mysqlc.New(proto, "", endpoint, username, password)
84+
conn := mysqlts.New(proto, "", endpoint, username, password)
7685

7786
err := conn.Connect()
7887
if err != nil {
7988
return nil, err
8089
}
8190

82-
return conn, nil
91+
major, minor, patch, err := mysqlVersion(conn)
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
return &providerConfiguration{
97+
Conn: conn,
98+
VersionMajor: major,
99+
VersionMinor: minor,
100+
VersionPatch: patch,
101+
}, nil
83102
}
84103

85104
var identQuoteReplacer = strings.NewReplacer("`", "``")
86105

87106
func quoteIdentifier(in string) string {
88107
return fmt.Sprintf("`%s`", identQuoteReplacer.Replace(in))
89108
}
109+
110+
func mysqlVersion(conn mysqlc.Conn) (uint, uint, uint, error) {
111+
rows, _, err := conn.Query("SELECT VERSION()")
112+
if err != nil {
113+
return 0, 0, 0, err
114+
}
115+
if len(rows) == 0 {
116+
return 0, 0, 0, fmt.Errorf("SELECT VERSION() returned an empty set")
117+
}
118+
119+
versionString := rows[0].Str(0)
120+
version := strings.Split(versionString, ".")
121+
invalidVersionErr := fmt.Errorf("Invalid major.minor.patch in %q", versionString)
122+
if len(version) != 3 {
123+
return 0, 0, 0, invalidVersionErr
124+
}
125+
126+
major, err := strconv.ParseUint(version[0], 10, 32)
127+
if err != nil {
128+
return 0, 0, 0, invalidVersionErr
129+
}
130+
131+
minor, err := strconv.ParseUint(version[1], 10, 32)
132+
if err != nil {
133+
return 0, 0, 0, invalidVersionErr
134+
}
135+
136+
patch, err := strconv.ParseUint(version[2], 10, 32)
137+
if err != nil {
138+
return 0, 0, 0, invalidVersionErr
139+
}
140+
141+
return uint(major), uint(minor), uint(patch), nil
142+
}

builtin/providers/mysql/resource_database.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func resourceDatabase() *schema.Resource {
4343
}
4444

4545
func CreateDatabase(d *schema.ResourceData, meta interface{}) error {
46-
conn := meta.(mysqlc.Conn)
46+
conn := meta.(*providerConfiguration).Conn
4747

4848
stmtSQL := databaseConfigSQL("CREATE", d)
4949
log.Println("Executing statement:", stmtSQL)
@@ -59,7 +59,7 @@ func CreateDatabase(d *schema.ResourceData, meta interface{}) error {
5959
}
6060

6161
func UpdateDatabase(d *schema.ResourceData, meta interface{}) error {
62-
conn := meta.(mysqlc.Conn)
62+
conn := meta.(*providerConfiguration).Conn
6363

6464
stmtSQL := databaseConfigSQL("ALTER", d)
6565
log.Println("Executing statement:", stmtSQL)
@@ -73,7 +73,7 @@ func UpdateDatabase(d *schema.ResourceData, meta interface{}) error {
7373
}
7474

7575
func ReadDatabase(d *schema.ResourceData, meta interface{}) error {
76-
conn := meta.(mysqlc.Conn)
76+
conn := meta.(*providerConfiguration).Conn
7777

7878
// This is kinda flimsy-feeling, since it depends on the formatting
7979
// of the SHOW CREATE DATABASE output... but this data doesn't seem
@@ -124,7 +124,7 @@ func ReadDatabase(d *schema.ResourceData, meta interface{}) error {
124124
}
125125

126126
func DeleteDatabase(d *schema.ResourceData, meta interface{}) error {
127-
conn := meta.(mysqlc.Conn)
127+
conn := meta.(*providerConfiguration).Conn
128128

129129
name := d.Id()
130130
stmtSQL := "DROP DATABASE " + quoteIdentifier(name)

builtin/providers/mysql/resource_database_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func testAccDatabaseCheck(rn string, name *string) resource.TestCheckFunc {
3939
return fmt.Errorf("database id not set")
4040
}
4141

42-
conn := testAccProvider.Meta().(mysqlc.Conn)
42+
conn := testAccProvider.Meta().(*providerConfiguration).Conn
4343
rows, _, err := conn.Query("SHOW CREATE DATABASE terraform_acceptance_test")
4444
if err != nil {
4545
return fmt.Errorf("error reading database: %s", err)
@@ -66,7 +66,7 @@ func testAccDatabaseCheck(rn string, name *string) resource.TestCheckFunc {
6666

6767
func testAccDatabaseCheckDestroy(name string) resource.TestCheckFunc {
6868
return func(s *terraform.State) error {
69-
conn := testAccProvider.Meta().(mysqlc.Conn)
69+
conn := testAccProvider.Meta().(*providerConfiguration).Conn
7070

7171
_, _, err := conn.Query("SHOW CREATE DATABASE terraform_acceptance_test")
7272
if err == nil {

builtin/providers/mysql/resource_grant.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"log"
66
"strings"
77

8-
mysqlc "github.com/ziutek/mymysql/mysql"
9-
108
"github.com/hashicorp/terraform/helper/schema"
119
)
1210

@@ -56,7 +54,7 @@ func resourceGrant() *schema.Resource {
5654
}
5755

5856
func CreateGrant(d *schema.ResourceData, meta interface{}) error {
59-
conn := meta.(mysqlc.Conn)
57+
conn := meta.(*providerConfiguration).Conn
6058

6159
// create a comma-delimited string of privileges
6260
var privileges string
@@ -95,7 +93,7 @@ func ReadGrant(d *schema.ResourceData, meta interface{}) error {
9593
}
9694

9795
func DeleteGrant(d *schema.ResourceData, meta interface{}) error {
98-
conn := meta.(mysqlc.Conn)
96+
conn := meta.(*providerConfiguration).Conn
9997

10098
stmtSQL := fmt.Sprintf("REVOKE GRANT OPTION ON %s.* FROM '%s'@'%s'",
10199
d.Get("database").(string),

builtin/providers/mysql/resource_grant_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func testAccPrivilegeExists(rn string, privilege string) resource.TestCheckFunc
4747
user := userhost[0]
4848
host := userhost[1]
4949

50-
conn := testAccProvider.Meta().(mysqlc.Conn)
50+
conn := testAccProvider.Meta().(*providerConfiguration).Conn
5151
stmtSQL := fmt.Sprintf("SHOW GRANTS for '%s'@'%s'", user, host)
5252
log.Println("Executing statement:", stmtSQL)
5353
rows, _, err := conn.Query(stmtSQL)
@@ -77,7 +77,7 @@ func testAccPrivilegeExists(rn string, privilege string) resource.TestCheckFunc
7777
}
7878

7979
func testAccGrantCheckDestroy(s *terraform.State) error {
80-
conn := testAccProvider.Meta().(mysqlc.Conn)
80+
conn := testAccProvider.Meta().(*providerConfiguration).Conn
8181

8282
for _, rs := range s.RootModule().Resources {
8383
if rs.Type != "mysql_grant" {

builtin/providers/mysql/resource_user.go

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"fmt"
55
"log"
66

7-
mysqlc "github.com/ziutek/mymysql/mysql"
8-
97
"github.com/hashicorp/terraform/helper/schema"
108
)
119

@@ -40,7 +38,7 @@ func resourceUser() *schema.Resource {
4038
}
4139

4240
func CreateUser(d *schema.ResourceData, meta interface{}) error {
43-
conn := meta.(mysqlc.Conn)
41+
conn := meta.(*providerConfiguration).Conn
4442

4543
stmtSQL := fmt.Sprintf("CREATE USER '%s'@'%s'",
4644
d.Get("user").(string),
@@ -64,17 +62,29 @@ func CreateUser(d *schema.ResourceData, meta interface{}) error {
6462
}
6563

6664
func UpdateUser(d *schema.ResourceData, meta interface{}) error {
67-
conn := meta.(mysqlc.Conn)
65+
conf := meta.(*providerConfiguration)
6866

6967
if d.HasChange("password") {
7068
_, newpw := d.GetChange("password")
71-
stmtSQL := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'",
72-
d.Get("user").(string),
73-
d.Get("host").(string),
74-
newpw.(string))
69+
var stmtSQL string
70+
71+
/* ALTER USER syntax introduced in MySQL 5.7.6 deprecates SET PASSWORD (GH-8230) */
72+
if conf.VersionMajor > 5 ||
73+
(conf.VersionMajor == 5 && conf.VersionMinor > 7) ||
74+
(conf.VersionMajor == 5 && conf.VersionMinor == 7 && conf.VersionPatch >= 6) {
75+
stmtSQL = fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'",
76+
d.Get("user").(string),
77+
d.Get("host").(string),
78+
newpw.(string))
79+
} else {
80+
stmtSQL = fmt.Sprintf("SET PASSWORD FOR '%s'@'%s' = PASSWORD('%s')",
81+
d.Get("user").(string),
82+
d.Get("host").(string),
83+
newpw.(string))
84+
}
7585

7686
log.Println("Executing query:", stmtSQL)
77-
_, _, err := conn.Query(stmtSQL)
87+
_, _, err := conf.Conn.Query(stmtSQL)
7888
if err != nil {
7989
return err
8090
}
@@ -89,7 +99,7 @@ func ReadUser(d *schema.ResourceData, meta interface{}) error {
8999
}
90100

91101
func DeleteUser(d *schema.ResourceData, meta interface{}) error {
92-
conn := meta.(mysqlc.Conn)
102+
conn := meta.(*providerConfiguration).Conn
93103

94104
stmtSQL := fmt.Sprintf("DROP USER '%s'@'%s'",
95105
d.Get("user").(string),

builtin/providers/mysql/resource_user_test.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"log"
66
"testing"
77

8-
mysqlc "github.com/ziutek/mymysql/mysql"
9-
108
"github.com/hashicorp/terraform/helper/resource"
119
"github.com/hashicorp/terraform/terraform"
1210
)
@@ -26,6 +24,15 @@ func TestAccUser(t *testing.T) {
2624
resource.TestCheckResourceAttr("mysql_user.test", "password", "password"),
2725
),
2826
},
27+
resource.TestStep{
28+
Config: testAccUserConfig_newPass,
29+
Check: resource.ComposeTestCheckFunc(
30+
testAccUserExists("mysql_user.test"),
31+
resource.TestCheckResourceAttr("mysql_user.test", "user", "jdoe"),
32+
resource.TestCheckResourceAttr("mysql_user.test", "host", "example.com"),
33+
resource.TestCheckResourceAttr("mysql_user.test", "password", "password2"),
34+
),
35+
},
2936
},
3037
})
3138
}
@@ -41,7 +48,7 @@ func testAccUserExists(rn string) resource.TestCheckFunc {
4148
return fmt.Errorf("user id not set")
4249
}
4350

44-
conn := testAccProvider.Meta().(mysqlc.Conn)
51+
conn := testAccProvider.Meta().(*providerConfiguration).Conn
4552
stmtSQL := fmt.Sprintf("SELECT count(*) from mysql.user where CONCAT(user, '@', host) = '%s'", rs.Primary.ID)
4653
log.Println("Executing statement:", stmtSQL)
4754
rows, _, err := conn.Query(stmtSQL)
@@ -57,7 +64,7 @@ func testAccUserExists(rn string) resource.TestCheckFunc {
5764
}
5865

5966
func testAccUserCheckDestroy(s *terraform.State) error {
60-
conn := testAccProvider.Meta().(mysqlc.Conn)
67+
conn := testAccProvider.Meta().(*providerConfiguration).Conn
6168

6269
for _, rs := range s.RootModule().Resources {
6370
if rs.Type != "mysql_user" {
@@ -84,3 +91,11 @@ resource "mysql_user" "test" {
8491
password = "password"
8592
}
8693
`
94+
95+
const testAccUserConfig_newPass = `
96+
resource "mysql_user" "test" {
97+
user = "jdoe"
98+
host = "example.com"
99+
password = "password2"
100+
}
101+
`

0 commit comments

Comments
 (0)