Skip to content

Commit

Permalink
added the ability to select a database when creating a server resourc…
Browse files Browse the repository at this point in the history
…e and user mapping
  • Loading branch information
a.leonov committed Dec 13, 2024
1 parent a9e6984 commit 4368555
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 16 deletions.
28 changes: 23 additions & 5 deletions postgresql/resource_postgresql_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
serverFDWAttr = "fdw_name"
serverOptionsAttr = "options"
serverDropCascadeAttr = "drop_cascade"
serverDatabaseAttr = "database"
)

func resourcePostgreSQLServer() *schema.Resource {
Expand Down Expand Up @@ -74,6 +75,12 @@ func resourcePostgreSQLServer() *schema.Resource {
Default: false,
Description: "Automatically drop objects that depend on the server (such as user mappings), and in turn all objects that depend on those objects. Drop RESTRICT is the default",
},
serverDatabaseAttr: {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Specifies the database in which the server will be created",
},
},
}
}
Expand All @@ -87,6 +94,7 @@ func resourcePostgreSQLServerCreate(db *DBConnection, d *schema.ResourceData) er
}

serverName := d.Get(serverNameAttr).(string)
databaseName := getDatabaseForServer(d, db.client.databaseName)

b := bytes.NewBufferString("CREATE SERVER ")
fmt.Fprint(b, pq.QuoteIdentifier(serverName))
Expand Down Expand Up @@ -115,7 +123,7 @@ func resourcePostgreSQLServerCreate(db *DBConnection, d *schema.ResourceData) er
fmt.Fprint(b, " ) ")
}

txn, err := startTransaction(db.client, "")
txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}
Expand Down Expand Up @@ -147,6 +155,13 @@ func resourcePostgreSQLServerCreate(db *DBConnection, d *schema.ResourceData) er
return resourcePostgreSQLServerReadImpl(db, d)
}

func getDatabaseForServer(d *schema.ResourceData, defaultDatabase string) string {
if v, ok := d.GetOk(serverDatabaseAttr); ok {
return v.(string)
}
return defaultDatabase
}

func resourcePostgreSQLServerRead(db *DBConnection, d *schema.ResourceData) error {
if !db.featureSupported(featureServer) {
return fmt.Errorf(
Expand All @@ -160,7 +175,8 @@ func resourcePostgreSQLServerRead(db *DBConnection, d *schema.ResourceData) erro

func resourcePostgreSQLServerReadImpl(db *DBConnection, d *schema.ResourceData) error {
serverName := d.Get(serverNameAttr).(string)
txn, err := startTransaction(db.client, "")
databaseName := getDatabaseForServer(d, db.client.databaseName)
txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}
Expand Down Expand Up @@ -193,6 +209,7 @@ func resourcePostgreSQLServerReadImpl(db *DBConnection, d *schema.ResourceData)
d.Set(serverOwnerAttr, serverOwner)
d.Set(serverOptionsAttr, mappedOptions)
d.Set(serverFDWAttr, serverFDW)
d.Set(serverDatabaseAttr, databaseName)
d.SetId(serverName)

return nil
Expand All @@ -207,8 +224,9 @@ func resourcePostgreSQLServerDelete(db *DBConnection, d *schema.ResourceData) er
}

serverName := d.Get(serverNameAttr).(string)
databaseName := getDatabaseForServer(d, db.client.databaseName)

txn, err := startTransaction(db.client, "")
txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}
Expand Down Expand Up @@ -240,8 +258,8 @@ func resourcePostgreSQLServerUpdate(db *DBConnection, d *schema.ResourceData) er
db.version,
)
}

txn, err := startTransaction(db.client, "")
databaseName := getDatabaseForServer(d, db.client.databaseName)
txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}
Expand Down
56 changes: 45 additions & 11 deletions postgresql/resource_postgresql_user_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const (
userMappingUserNameAttr = "user_name"
userMappingServerNameAttr = "server_name"
userMappingOptionsAttr = "options"
userMappingDatabaseAttr = "database"
)

func resourcePostgreSQLUserMapping() *schema.Resource {
Expand Down Expand Up @@ -48,6 +49,12 @@ func resourcePostgreSQLUserMapping() *schema.Resource {
Optional: true,
Description: "This clause specifies the options of the user mapping. The options typically define the actual user name and password of the mapping. Option names must be unique. The allowed option names and values are specific to the server's foreign-data wrapper",
},
userMappingDatabaseAttr: {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Specifies the database in which the server will be created",
},
},
}
}
Expand All @@ -62,7 +69,14 @@ func resourcePostgreSQLUserMappingCreate(db *DBConnection, d *schema.ResourceDat

username := d.Get(userMappingUserNameAttr).(string)
serverName := d.Get(userMappingServerNameAttr).(string)
databaseName := getDatabaseForUserMapping(d, db.client.databaseName)

txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}
defer deferredRollback(txn)
log.Printf("[WARN] PostgreSQL create function username: (%s), servername: (%s), databaseName: (%s)", username, serverName, databaseName)
b := bytes.NewBufferString("CREATE USER MAPPING ")
fmt.Fprint(b, " FOR ", pq.QuoteIdentifier(username))
fmt.Fprint(b, " SERVER ", pq.QuoteIdentifier(serverName))
Expand All @@ -81,12 +95,15 @@ func resourcePostgreSQLUserMappingCreate(db *DBConnection, d *schema.ResourceDat
fmt.Fprint(b, " ) ")
}

if _, err := db.Exec(b.String()); err != nil {
if _, err := txn.Exec(b.String()); err != nil {
return fmt.Errorf("Could not create user mapping: %w", err)
}
if err = txn.Commit(); err != nil {
return fmt.Errorf("Could commit user mapping: %w", err)
}

d.SetId(generateUserMappingID(d))

d.SetId(generateUserMappingID(d, databaseName))
log.Printf("[WARN] PostgreSQL create function SetId: (%s)", d.SetId)
return resourcePostgreSQLUserMappingReadImpl(db, d)
}

Expand All @@ -104,13 +121,14 @@ func resourcePostgreSQLUserMappingRead(db *DBConnection, d *schema.ResourceData)
func resourcePostgreSQLUserMappingReadImpl(db *DBConnection, d *schema.ResourceData) error {
username := d.Get(userMappingUserNameAttr).(string)
serverName := d.Get(userMappingServerNameAttr).(string)
databaseName := getDatabaseForUserMapping(d, db.client.databaseName)

txn, err := startTransaction(db.client, "")
txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}
defer deferredRollback(txn)

log.Printf("[WARN] PostgreSQL ReadImpl function username: (%s), servername: (%s), databaseName: (%s)", username, serverName, databaseName)
var userMappingOptions []string
query := "SELECT umoptions FROM information_schema._pg_user_mappings WHERE authorization_identifier = $1 and foreign_server_name = $2"
err = txn.QueryRow(query, username, serverName).Scan(pq.Array(&userMappingOptions))
Expand Down Expand Up @@ -139,8 +157,9 @@ func resourcePostgreSQLUserMappingReadImpl(db *DBConnection, d *schema.ResourceD
d.Set(userMappingUserNameAttr, username)
d.Set(userMappingServerNameAttr, serverName)
d.Set(userMappingOptionsAttr, mappedOptions)
d.SetId(generateUserMappingID(d))

d.Set(userMappingDatabaseAttr, databaseName)
d.SetId(generateUserMappingID(d, databaseName))
log.Printf("[WARN] PostgreSQL ReadImpl function d.SetId: (%s)", d.SetId)
return nil
}

Expand All @@ -154,8 +173,9 @@ func resourcePostgreSQLUserMappingDelete(db *DBConnection, d *schema.ResourceDat

username := d.Get(userMappingUserNameAttr).(string)
serverName := d.Get(userMappingServerNameAttr).(string)
databaseName := getDatabaseForUserMapping(d, db.client.databaseName)

txn, err := startTransaction(db.client, "")
txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}
Expand Down Expand Up @@ -197,6 +217,12 @@ func setUserMappingOptionsIfChanged(db *DBConnection, d *schema.ResourceData) er

username := d.Get(userMappingUserNameAttr).(string)
serverName := d.Get(userMappingServerNameAttr).(string)
databaseName := getDatabaseForUserMapping(d, db.client.databaseName)

txn, err := startTransaction(db.client, databaseName)
if err != nil {
return err
}

b := bytes.NewBufferString("ALTER USER MAPPING ")
fmt.Fprintf(b, " FOR %s SERVER %s ", pq.QuoteIdentifier(username), pq.QuoteIdentifier(serverName))
Expand Down Expand Up @@ -229,16 +255,24 @@ func setUserMappingOptionsIfChanged(db *DBConnection, d *schema.ResourceData) er

fmt.Fprint(b, " ) ")

if _, err := db.Exec(b.String()); err != nil {
if _, err := txn.Exec(b.String()); err != nil {
return fmt.Errorf("Error updating user mapping options: %w", err)
}

return nil
}

func generateUserMappingID(d *schema.ResourceData) string {
func generateUserMappingID(d *schema.ResourceData, databaseName string) string {
return strings.Join([]string{
d.Get(userMappingUserNameAttr).(string),
d.Get(userMappingServerNameAttr).(string),
databaseName,
d.Get(userMappingDatabaseAttr).(string),
}, ".")
}

func getDatabaseForUserMapping(d *schema.ResourceData, defaultDatabase string) string {
if v, ok := d.GetOk(userMappingDatabaseAttr); ok {
return v.(string)
}
return defaultDatabase
}
1 change: 1 addition & 0 deletions website/docs/r/postgresql_server.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ resource "postgresql_server" "myserver_file" {
## Argument Reference

* `server_name` - (Required) The name of the foreign server to be created.
* `database` - (Optional) Which database to create the extension on. Defaults to provider database.
* `fdw_name` - (Required) The name of the foreign-data wrapper that manages the server.
Changing this value
will force the creation of a new resource as this value can only be set
Expand Down
1 change: 1 addition & 0 deletions website/docs/r/postgresql_user_mapping.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ Changing this value
Changing this value
will force the creation of a new resource as this value can only be set
when the user mapping is created.
* `database` - (Optional) Which database to create the extension on. Defaults to provider database.
* `options` - (Optional) This clause specifies the options of the user mapping. The options typically define the actual user name and password of the mapping. Option names must be unique. The allowed option names and values are specific to the server's foreign-data wrapper.

0 comments on commit 4368555

Please sign in to comment.