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  }