2016-10-04 12:05:51 +02:00
package postgresql
import (
2016-12-12 22:15:57 +01:00
"bytes"
2016-11-02 15:36:39 +01:00
"database/sql"
2016-12-12 22:15:57 +01:00
"errors"
2016-10-04 12:05:51 +02:00
"fmt"
2016-12-12 10:33:02 +01:00
"log"
2016-10-04 12:05:51 +02:00
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/schema"
"github.com/lib/pq"
)
2016-12-12 22:15:57 +01:00
const (
extNameAttr = "name"
extSchemaAttr = "schema"
)
2016-10-04 12:05:51 +02:00
func resourcePostgreSQLExtension ( ) * schema . Resource {
return & schema . Resource {
Create : resourcePostgreSQLExtensionCreate ,
2016-11-02 15:36:39 +01:00
Read : resourcePostgreSQLExtensionRead ,
2016-12-12 22:15:57 +01:00
Update : resourcePostgreSQLExtensionUpdate ,
2016-10-04 12:05:51 +02:00
Delete : resourcePostgreSQLExtensionDelete ,
2016-12-12 10:33:02 +01:00
Importer : & schema . ResourceImporter {
State : schema . ImportStatePassthrough ,
} ,
2016-10-04 12:05:51 +02:00
Schema : map [ string ] * schema . Schema {
2016-12-12 22:15:57 +01:00
extNameAttr : {
2016-10-04 12:05:51 +02:00
Type : schema . TypeString ,
Required : true ,
ForceNew : true ,
} ,
2016-12-12 22:15:57 +01:00
extSchemaAttr : {
Type : schema . TypeString ,
Optional : true ,
Computed : true ,
Description : "Sets the schema of an extension" ,
} ,
2016-10-04 12:05:51 +02:00
} ,
}
}
func resourcePostgreSQLExtensionCreate ( d * schema . ResourceData , meta interface { } ) error {
2016-12-12 10:33:02 +01:00
c := meta . ( * Client )
conn , err := c . Connect ( )
2016-10-04 12:05:51 +02:00
if err != nil {
return err
}
defer conn . Close ( )
2016-12-12 22:15:57 +01:00
extName := d . Get ( extNameAttr ) . ( string )
b := bytes . NewBufferString ( "CREATE EXTENSION " )
fmt . Fprintf ( b , pq . QuoteIdentifier ( extName ) )
2016-10-04 12:05:51 +02:00
2016-12-12 22:15:57 +01:00
if v , ok := d . GetOk ( extSchemaAttr ) ; ok {
fmt . Fprint ( b , " SCHEMA " , pq . QuoteIdentifier ( v . ( string ) ) )
}
query := b . String ( )
2016-10-04 12:05:51 +02:00
_ , err = conn . Query ( query )
if err != nil {
return errwrap . Wrapf ( "Error creating extension: {{err}}" , err )
}
2016-12-12 22:15:57 +01:00
d . SetId ( extName )
2016-10-04 12:05:51 +02:00
2016-11-02 15:36:39 +01:00
return resourcePostgreSQLExtensionRead ( d , meta )
}
func resourcePostgreSQLExtensionRead ( d * schema . ResourceData , meta interface { } ) error {
2016-12-12 10:33:02 +01:00
c := meta . ( * Client )
conn , err := c . Connect ( )
2016-11-02 15:36:39 +01:00
if err != nil {
return err
}
defer conn . Close ( )
2016-12-12 22:15:57 +01:00
extID := d . Get ( extNameAttr ) . ( string )
2016-11-02 15:36:39 +01:00
2016-12-12 22:15:57 +01:00
var extName , extSchema string
err = conn . QueryRow ( "SELECT e.extname, n.nspname FROM pg_catalog.pg_extension e, pg_catalog.pg_namespace n WHERE n.oid = e.extnamespace AND e.extname = $1" , extID ) . Scan ( & extName , & extSchema )
2016-11-02 15:36:39 +01:00
switch {
case err == sql . ErrNoRows :
2016-12-12 10:33:02 +01:00
log . Printf ( "[WARN] PostgreSQL extension (%s) not found" , d . Id ( ) )
2016-11-02 15:36:39 +01:00
d . SetId ( "" )
return nil
case err != nil :
return errwrap . Wrapf ( "Error reading extension: {{err}}" , err )
default :
2016-12-12 22:15:57 +01:00
d . Set ( extNameAttr , extName )
d . Set ( extSchemaAttr , extSchema )
d . SetId ( extName )
2016-11-02 15:36:39 +01:00
return nil
}
2016-10-04 12:05:51 +02:00
}
func resourcePostgreSQLExtensionDelete ( d * schema . ResourceData , meta interface { } ) error {
2016-12-12 10:33:02 +01:00
c := meta . ( * Client )
conn , err := c . Connect ( )
2016-10-04 12:05:51 +02:00
if err != nil {
return err
}
defer conn . Close ( )
2016-12-12 22:15:57 +01:00
extName := d . Get ( extNameAttr ) . ( string )
2016-10-04 12:05:51 +02:00
2016-12-12 22:15:57 +01:00
query := fmt . Sprintf ( "DROP EXTENSION %s" , pq . QuoteIdentifier ( extName ) )
2016-10-04 12:05:51 +02:00
_ , err = conn . Query ( query )
if err != nil {
return errwrap . Wrapf ( "Error deleting extension: {{err}}" , err )
}
d . SetId ( "" )
return nil
}
2016-12-12 22:15:57 +01:00
func resourcePostgreSQLExtensionUpdate ( d * schema . ResourceData , meta interface { } ) error {
c := meta . ( * Client )
conn , err := c . Connect ( )
if err != nil {
return err
}
defer conn . Close ( )
// Can't rename a schema
if err := setExtSchema ( conn , d ) ; err != nil {
return err
}
return resourcePostgreSQLExtensionRead ( d , meta )
}
func setExtSchema ( conn * sql . DB , d * schema . ResourceData ) error {
if ! d . HasChange ( extSchemaAttr ) {
return nil
}
oraw , nraw := d . GetChange ( extSchemaAttr )
o := oraw . ( string )
n := nraw . ( string )
if n == "" {
return errors . New ( "Error setting extension name to an empty string" )
}
query := fmt . Sprintf ( "ALTER EXTENSION %s SET SCHEMA %s" , pq . QuoteIdentifier ( o ) , pq . QuoteIdentifier ( n ) )
if _ , err := conn . Query ( query ) ; err != nil {
return errwrap . Wrapf ( "Error updating extension SCHEMA: {{err}}" , err )
}
return nil
}