github.com/daveadams/terraform@v0.6.4-0.20160830094355-13ce74975936/builtin/providers/mysql/provider.go (about) 1 package mysql 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 mysqlc "github.com/ziutek/mymysql/mysql" 9 mysqlts "github.com/ziutek/mymysql/thrsafe" 10 11 "github.com/hashicorp/terraform/helper/schema" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 type providerConfiguration struct { 16 Conn mysqlc.Conn 17 VersionMajor uint 18 VersionMinor uint 19 VersionPatch uint 20 } 21 22 func Provider() terraform.ResourceProvider { 23 return &schema.Provider{ 24 Schema: map[string]*schema.Schema{ 25 "endpoint": &schema.Schema{ 26 Type: schema.TypeString, 27 Required: true, 28 DefaultFunc: schema.EnvDefaultFunc("MYSQL_ENDPOINT", nil), 29 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 30 value := v.(string) 31 if value == "" { 32 errors = append(errors, fmt.Errorf("Endpoint must not be an empty string")) 33 } 34 35 return 36 }, 37 }, 38 39 "username": &schema.Schema{ 40 Type: schema.TypeString, 41 Required: true, 42 DefaultFunc: schema.EnvDefaultFunc("MYSQL_USERNAME", nil), 43 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 44 value := v.(string) 45 if value == "" { 46 errors = append(errors, fmt.Errorf("Username must not be an empty string")) 47 } 48 49 return 50 }, 51 }, 52 53 "password": &schema.Schema{ 54 Type: schema.TypeString, 55 Optional: true, 56 DefaultFunc: schema.EnvDefaultFunc("MYSQL_PASSWORD", nil), 57 }, 58 }, 59 60 ResourcesMap: map[string]*schema.Resource{ 61 "mysql_database": resourceDatabase(), 62 "mysql_user": resourceUser(), 63 "mysql_grant": resourceGrant(), 64 }, 65 66 ConfigureFunc: providerConfigure, 67 } 68 } 69 70 func providerConfigure(d *schema.ResourceData) (interface{}, error) { 71 72 var username = d.Get("username").(string) 73 var password = d.Get("password").(string) 74 var endpoint = d.Get("endpoint").(string) 75 76 proto := "tcp" 77 if endpoint[0] == '/' { 78 proto = "unix" 79 } 80 81 // mysqlts is the thread-safe implementation of mymysql, so we can 82 // safely re-use the same connection between multiple parallel 83 // operations. 84 conn := mysqlts.New(proto, "", endpoint, username, password) 85 86 err := conn.Connect() 87 if err != nil { 88 return nil, err 89 } 90 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 102 } 103 104 var identQuoteReplacer = strings.NewReplacer("`", "``") 105 106 func quoteIdentifier(in string) string { 107 return fmt.Sprintf("`%s`", identQuoteReplacer.Replace(in)) 108 } 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 }