2016-01-13 21:33:08 +00:00
package google
import (
"fmt"
"log"
2017-05-22 20:43:11 +00:00
"strings"
2016-01-13 21:33:08 +00:00
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/sqladmin/v1beta4"
)
func resourceSqlUser ( ) * schema . Resource {
return & schema . Resource {
Create : resourceSqlUserCreate ,
Read : resourceSqlUserRead ,
Update : resourceSqlUserUpdate ,
Delete : resourceSqlUserDelete ,
2017-05-22 20:43:11 +00:00
Importer : & schema . ResourceImporter {
2018-02-09 21:43:49 +00:00
State : resourceSqlUserImporter ,
2017-05-22 20:43:11 +00:00
} ,
SchemaVersion : 1 ,
MigrateState : resourceSqlUserMigrateState ,
2016-01-13 21:33:08 +00:00
Schema : map [ string ] * schema . Schema {
2016-04-10 21:34:15 +00:00
"host" : & schema . Schema {
2016-01-13 21:33:08 +00:00
Type : schema . TypeString ,
2018-02-09 21:43:49 +00:00
Optional : true ,
2016-01-13 21:33:08 +00:00
ForceNew : true ,
} ,
2016-04-10 21:34:15 +00:00
"instance" : & schema . Schema {
2016-01-13 21:33:08 +00:00
Type : schema . TypeString ,
Required : true ,
2016-04-10 21:34:15 +00:00
ForceNew : true ,
2016-01-13 21:33:08 +00:00
} ,
2016-04-10 21:34:15 +00:00
"name" : & schema . Schema {
2016-01-13 21:33:08 +00:00
Type : schema . TypeString ,
Required : true ,
ForceNew : true ,
} ,
2016-04-10 21:34:15 +00:00
"password" : & schema . Schema {
2017-05-22 20:43:11 +00:00
Type : schema . TypeString ,
2018-02-07 19:59:23 +00:00
Optional : true ,
2017-05-22 20:43:11 +00:00
Sensitive : true ,
2016-01-13 21:33:08 +00:00
} ,
2016-04-10 16:59:57 +00:00
"project" : & schema . Schema {
Type : schema . TypeString ,
Optional : true ,
2017-11-28 00:32:20 +00:00
Computed : true ,
2016-04-10 16:59:57 +00:00
ForceNew : true ,
} ,
2016-01-13 21:33:08 +00:00
} ,
}
}
func resourceSqlUserCreate ( d * schema . ResourceData , meta interface { } ) error {
config := meta . ( * Config )
2016-04-10 16:59:57 +00:00
project , err := getProject ( d , config )
if err != nil {
return err
}
2016-01-13 21:33:08 +00:00
name := d . Get ( "name" ) . ( string )
instance := d . Get ( "instance" ) . ( string )
password := d . Get ( "password" ) . ( string )
host := d . Get ( "host" ) . ( string )
user := & sqladmin . User {
Name : name ,
Instance : instance ,
Password : password ,
Host : host ,
}
2017-05-31 19:19:27 +00:00
mutexKV . Lock ( instanceMutexKey ( project , instance ) )
defer mutexKV . Unlock ( instanceMutexKey ( project , instance ) )
2016-01-13 21:33:08 +00:00
op , err := config . clientSqlAdmin . Users . Insert ( project , instance ,
user ) . Do ( )
if err != nil {
return fmt . Errorf ( "Error, failed to insert " +
"user %s into instance %s: %s" , name , instance , err )
}
2017-05-22 20:43:11 +00:00
d . SetId ( fmt . Sprintf ( "%s/%s" , instance , name ) )
2017-09-27 00:01:52 +00:00
err = sqladminOperationWait ( config , op , project , "Insert User" )
2016-01-13 21:33:08 +00:00
if err != nil {
return fmt . Errorf ( "Error, failure waiting for insertion of %s " +
"into %s: %s" , name , instance , err )
}
return resourceSqlUserRead ( d , meta )
}
func resourceSqlUserRead ( d * schema . ResourceData , meta interface { } ) error {
config := meta . ( * Config )
2016-04-10 16:59:57 +00:00
project , err := getProject ( d , config )
if err != nil {
return err
}
2018-02-09 21:43:49 +00:00
instance := d . Get ( "instance" ) . ( string )
name := d . Get ( "name" ) . ( string )
host := d . Get ( "host" ) . ( string )
2016-01-13 21:33:08 +00:00
users , err := config . clientSqlAdmin . Users . List ( project , instance ) . Do ( )
if err != nil {
2017-05-09 23:00:47 +00:00
return handleNotFoundError ( err , d , fmt . Sprintf ( "SQL User %q in instance %q" , name , instance ) )
2016-01-13 21:33:08 +00:00
}
2017-05-22 20:43:11 +00:00
var user * sqladmin . User
for _ , currentUser := range users . Items {
2018-02-09 21:43:49 +00:00
if currentUser . Name == name && currentUser . Host == host {
2017-05-22 20:43:11 +00:00
user = currentUser
2016-01-13 21:33:08 +00:00
break
}
}
2017-05-22 20:43:11 +00:00
if user == nil {
2016-01-13 21:33:08 +00:00
log . Printf ( "[WARN] Removing SQL User %q because it's gone" , d . Get ( "name" ) . ( string ) )
d . SetId ( "" )
return nil
}
2017-05-22 20:43:11 +00:00
d . Set ( "host" , user . Host )
d . Set ( "instance" , user . Instance )
d . Set ( "name" , user . Name )
2017-11-28 00:32:20 +00:00
d . Set ( "project" , project )
2016-01-13 21:33:08 +00:00
return nil
}
func resourceSqlUserUpdate ( d * schema . ResourceData , meta interface { } ) error {
config := meta . ( * Config )
if d . HasChange ( "password" ) {
2016-04-10 16:59:57 +00:00
project , err := getProject ( d , config )
if err != nil {
return err
}
2016-01-13 21:33:08 +00:00
name := d . Get ( "name" ) . ( string )
instance := d . Get ( "instance" ) . ( string )
host := d . Get ( "host" ) . ( string )
password := d . Get ( "password" ) . ( string )
user := & sqladmin . User {
Name : name ,
Instance : instance ,
Password : password ,
Host : host ,
}
2017-05-31 19:19:27 +00:00
mutexKV . Lock ( instanceMutexKey ( project , instance ) )
defer mutexKV . Unlock ( instanceMutexKey ( project , instance ) )
2016-01-13 21:33:08 +00:00
op , err := config . clientSqlAdmin . Users . Update ( project , instance , host , name ,
user ) . Do ( )
if err != nil {
return fmt . Errorf ( "Error, failed to update" +
"user %s into user %s: %s" , name , instance , err )
}
2017-09-27 00:01:52 +00:00
err = sqladminOperationWait ( config , op , project , "Insert User" )
2016-01-13 21:33:08 +00:00
if err != nil {
return fmt . Errorf ( "Error, failure waiting for update of %s " +
"in %s: %s" , name , instance , err )
}
return resourceSqlUserRead ( d , meta )
}
return nil
}
func resourceSqlUserDelete ( d * schema . ResourceData , meta interface { } ) error {
config := meta . ( * Config )
2016-04-10 16:59:57 +00:00
project , err := getProject ( d , config )
if err != nil {
return err
}
2016-01-13 21:33:08 +00:00
name := d . Get ( "name" ) . ( string )
instance := d . Get ( "instance" ) . ( string )
host := d . Get ( "host" ) . ( string )
2017-05-31 19:19:27 +00:00
mutexKV . Lock ( instanceMutexKey ( project , instance ) )
defer mutexKV . Unlock ( instanceMutexKey ( project , instance ) )
2016-01-13 21:33:08 +00:00
op , err := config . clientSqlAdmin . Users . Delete ( project , instance , host , name ) . Do ( )
if err != nil {
return fmt . Errorf ( "Error, failed to delete" +
"user %s in instance %s: %s" , name ,
instance , err )
}
2017-09-27 00:01:52 +00:00
err = sqladminOperationWait ( config , op , project , "Delete User" )
2016-01-13 21:33:08 +00:00
if err != nil {
return fmt . Errorf ( "Error, failure waiting for deletion of %s " +
"in %s: %s" , name , instance , err )
}
return nil
}
2018-02-09 21:43:49 +00:00
func resourceSqlUserImporter ( d * schema . ResourceData , meta interface { } ) ( [ ] * schema . ResourceData , error ) {
parts := strings . Split ( d . Id ( ) , "/" )
if len ( parts ) == 2 {
d . Set ( "instance" , parts [ 0 ] )
d . Set ( "name" , parts [ 1 ] )
} else if len ( parts ) == 3 {
d . Set ( "instance" , parts [ 0 ] )
d . Set ( "host" , parts [ 1 ] )
d . Set ( "name" , parts [ 2 ] )
d . SetId ( fmt . Sprintf ( "%s/%s" , parts [ 0 ] , parts [ 2 ] ) )
} else {
return nil , fmt . Errorf ( "Invalid specifier. Expecting {instance}/{name} for 2nd generation instance and {instance}/{host}/{name} for 1st generation instance" )
}
return [ ] * schema . ResourceData { d } , nil
}