github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/postgresql/resource_postgresql_database.go (about)

     1  package postgresql
     2  
     3  import (
     4  	"database/sql"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/errwrap"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"github.com/lib/pq"
    11  )
    12  
    13  func resourcePostgreSQLDatabase() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourcePostgreSQLDatabaseCreate,
    16  		Read:   resourcePostgreSQLDatabaseRead,
    17  		Update: resourcePostgreSQLDatabaseUpdate,
    18  		Delete: resourcePostgreSQLDatabaseDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"name": {
    22  				Type:     schema.TypeString,
    23  				Required: true,
    24  				ForceNew: true,
    25  			},
    26  			"owner": {
    27  				Type:     schema.TypeString,
    28  				Optional: true,
    29  				Computed: true,
    30  			},
    31  		},
    32  	}
    33  }
    34  
    35  func resourcePostgreSQLDatabaseCreate(d *schema.ResourceData, meta interface{}) error {
    36  	client := meta.(*Client)
    37  	conn, err := client.Connect()
    38  	if err != nil {
    39  		return errwrap.Wrapf("Error connecting to PostgreSQL: {{err}}", err)
    40  	}
    41  	defer conn.Close()
    42  
    43  	dbName := d.Get("name").(string)
    44  	dbOwner := d.Get("owner").(string)
    45  	connUsername := client.username
    46  
    47  	var dbOwnerCfg string
    48  	if dbOwner != "" {
    49  		dbOwnerCfg = fmt.Sprintf("WITH OWNER=%s", pq.QuoteIdentifier(dbOwner))
    50  	} else {
    51  		dbOwnerCfg = ""
    52  	}
    53  
    54  	//needed in order to set the owner of the db if the connection user is not a superuser
    55  	err = grantRoleMembership(conn, dbOwner, connUsername)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	query := fmt.Sprintf("CREATE DATABASE %s %s", pq.QuoteIdentifier(dbName), dbOwnerCfg)
    61  	_, err = conn.Query(query)
    62  	if err != nil {
    63  		return errwrap.Wrapf(fmt.Sprintf("Error creating database %s: {{err}}", dbName), err)
    64  	}
    65  
    66  	d.SetId(dbName)
    67  
    68  	return resourcePostgreSQLDatabaseRead(d, meta)
    69  }
    70  
    71  func resourcePostgreSQLDatabaseDelete(d *schema.ResourceData, meta interface{}) error {
    72  	client := meta.(*Client)
    73  	conn, err := client.Connect()
    74  	if err != nil {
    75  		return errwrap.Wrapf("Error connecting to PostgreSQL: {{err}}", err)
    76  	}
    77  	defer conn.Close()
    78  
    79  	dbName := d.Get("name").(string)
    80  	connUsername := client.username
    81  	dbOwner := d.Get("owner").(string)
    82  	//needed in order to set the owner of the db if the connection user is not a superuser
    83  	err = grantRoleMembership(conn, dbOwner, connUsername)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	query := fmt.Sprintf("DROP DATABASE %s", pq.QuoteIdentifier(dbName))
    89  	_, err = conn.Query(query)
    90  	if err != nil {
    91  		return errwrap.Wrapf("Error dropping database: {{err}}", err)
    92  	}
    93  
    94  	d.SetId("")
    95  
    96  	return nil
    97  }
    98  
    99  func resourcePostgreSQLDatabaseRead(d *schema.ResourceData, meta interface{}) error {
   100  	client := meta.(*Client)
   101  	conn, err := client.Connect()
   102  	if err != nil {
   103  		return err
   104  	}
   105  	defer conn.Close()
   106  
   107  	dbName := d.Get("name").(string)
   108  
   109  	var owner string
   110  	err = conn.QueryRow("SELECT pg_catalog.pg_get_userbyid(d.datdba) from pg_database d WHERE datname=$1", dbName).Scan(&owner)
   111  	switch {
   112  	case err == sql.ErrNoRows:
   113  		d.SetId("")
   114  		return nil
   115  	case err != nil:
   116  		return errwrap.Wrapf("Error reading database: {{err}}", err)
   117  	default:
   118  		d.Set("owner", owner)
   119  		return nil
   120  	}
   121  }
   122  
   123  func resourcePostgreSQLDatabaseUpdate(d *schema.ResourceData, meta interface{}) error {
   124  	client := meta.(*Client)
   125  	conn, err := client.Connect()
   126  	if err != nil {
   127  		return err
   128  	}
   129  	defer conn.Close()
   130  
   131  	dbName := d.Get("name").(string)
   132  
   133  	if d.HasChange("owner") {
   134  		owner := d.Get("owner").(string)
   135  		if owner != "" {
   136  			query := fmt.Sprintf("ALTER DATABASE %s OWNER TO %s", pq.QuoteIdentifier(dbName), pq.QuoteIdentifier(owner))
   137  			_, err := conn.Query(query)
   138  			if err != nil {
   139  				return errwrap.Wrapf("Error updating owner: {{err}}", err)
   140  			}
   141  		}
   142  	}
   143  
   144  	return resourcePostgreSQLDatabaseRead(d, meta)
   145  }
   146  
   147  func grantRoleMembership(conn *sql.DB, dbOwner string, connUsername string) error {
   148  	if dbOwner != "" && dbOwner != connUsername {
   149  		query := fmt.Sprintf("GRANT %s TO %s", pq.QuoteIdentifier(dbOwner), pq.QuoteIdentifier(connUsername))
   150  		_, err := conn.Query(query)
   151  		if err != nil {
   152  			//is already member or role
   153  			if strings.Contains(err.Error(), "duplicate key value violates unique constraint") {
   154  				return nil
   155  			}
   156  			return errwrap.Wrapf("Error granting membership: {{err}}", err)
   157  		}
   158  	}
   159  	return nil
   160  }