github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/mysql/provider.go (about)

     1  package mysql
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/go-version"
     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  	ServerVersion *version.Version
    18  }
    19  
    20  func Provider() terraform.ResourceProvider {
    21  	return &schema.Provider{
    22  		Schema: map[string]*schema.Schema{
    23  			"endpoint": &schema.Schema{
    24  				Type:        schema.TypeString,
    25  				Required:    true,
    26  				DefaultFunc: schema.EnvDefaultFunc("MYSQL_ENDPOINT", nil),
    27  				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    28  					value := v.(string)
    29  					if value == "" {
    30  						errors = append(errors, fmt.Errorf("Endpoint must not be an empty string"))
    31  					}
    32  
    33  					return
    34  				},
    35  			},
    36  
    37  			"username": &schema.Schema{
    38  				Type:        schema.TypeString,
    39  				Required:    true,
    40  				DefaultFunc: schema.EnvDefaultFunc("MYSQL_USERNAME", nil),
    41  				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    42  					value := v.(string)
    43  					if value == "" {
    44  						errors = append(errors, fmt.Errorf("Username must not be an empty string"))
    45  					}
    46  
    47  					return
    48  				},
    49  			},
    50  
    51  			"password": &schema.Schema{
    52  				Type:        schema.TypeString,
    53  				Optional:    true,
    54  				DefaultFunc: schema.EnvDefaultFunc("MYSQL_PASSWORD", nil),
    55  			},
    56  		},
    57  
    58  		ResourcesMap: map[string]*schema.Resource{
    59  			"mysql_database": resourceDatabase(),
    60  			"mysql_user":     resourceUser(),
    61  			"mysql_grant":    resourceGrant(),
    62  		},
    63  
    64  		ConfigureFunc: providerConfigure,
    65  	}
    66  }
    67  
    68  func providerConfigure(d *schema.ResourceData) (interface{}, error) {
    69  
    70  	var username = d.Get("username").(string)
    71  	var password = d.Get("password").(string)
    72  	var endpoint = d.Get("endpoint").(string)
    73  
    74  	proto := "tcp"
    75  	if len(endpoint) > 0 && endpoint[0] == '/' {
    76  		proto = "unix"
    77  	}
    78  
    79  	// mysqlts is the thread-safe implementation of mymysql, so we can
    80  	// safely re-use the same connection between multiple parallel
    81  	// operations.
    82  	conn := mysqlts.New(proto, "", endpoint, username, password)
    83  
    84  	err := conn.Connect()
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	ver, err := serverVersion(conn)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	return &providerConfiguration{
    95  		Conn:          conn,
    96  		ServerVersion: ver,
    97  	}, nil
    98  }
    99  
   100  var identQuoteReplacer = strings.NewReplacer("`", "``")
   101  
   102  func quoteIdentifier(in string) string {
   103  	return fmt.Sprintf("`%s`", identQuoteReplacer.Replace(in))
   104  }
   105  
   106  func serverVersion(conn mysqlc.Conn) (*version.Version, error) {
   107  	rows, _, err := conn.Query("SELECT VERSION()")
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	if len(rows) == 0 {
   112  		return nil, fmt.Errorf("SELECT VERSION() returned an empty set")
   113  	}
   114  
   115  	return version.NewVersion(rows[0].Str(0))
   116  }