diff --git a/postgresql/resource_postgresql_server.go b/postgresql/resource_postgresql_server.go index e1c8e300..923cac6f 100644 --- a/postgresql/resource_postgresql_server.go +++ b/postgresql/resource_postgresql_server.go @@ -19,6 +19,7 @@ const ( serverFDWAttr = "fdw_name" serverOptionsAttr = "options" serverDropCascadeAttr = "drop_cascade" + serverDatabaseAttr = "database" ) func resourcePostgreSQLServer() *schema.Resource { @@ -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", + }, }, } } @@ -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)) @@ -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 } @@ -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( @@ -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 } @@ -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 @@ -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 } @@ -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 } diff --git a/postgresql/resource_postgresql_user_mapping.go b/postgresql/resource_postgresql_user_mapping.go index 891ef2b0..68414bb1 100644 --- a/postgresql/resource_postgresql_user_mapping.go +++ b/postgresql/resource_postgresql_user_mapping.go @@ -15,6 +15,7 @@ const ( userMappingUserNameAttr = "user_name" userMappingServerNameAttr = "server_name" userMappingOptionsAttr = "options" + userMappingDatabaseAttr = "database" ) func resourcePostgreSQLUserMapping() *schema.Resource { @@ -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", + }, }, } } @@ -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)) @@ -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) } @@ -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)) @@ -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 } @@ -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 } @@ -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)) @@ -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 +} diff --git a/website/docs/r/postgresql_server.html.markdown b/website/docs/r/postgresql_server.html.markdown index fc16ff03..fb7fdc79 100644 --- a/website/docs/r/postgresql_server.html.markdown +++ b/website/docs/r/postgresql_server.html.markdown @@ -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 diff --git a/website/docs/r/postgresql_user_mapping.html.markdown b/website/docs/r/postgresql_user_mapping.html.markdown index 20ecdd89..201c45c8 100644 --- a/website/docs/r/postgresql_user_mapping.html.markdown +++ b/website/docs/r/postgresql_user_mapping.html.markdown @@ -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.