Automatically perform a `REASSIGN OWNED` and `DROP OWNED BY` when
removing a PostgreSQL role. Add manual overrides if this isn't the desired behavior, but it should universally be the desired outcome except when a ROLE name is reused across multiple databases in the same PostgreSQL cluster, in which case the `skip_drop_role` is necessary for all but the last PostgreSQL provider.
This commit is contained in:
parent
2e3c843db3
commit
897609878f
|
@ -13,18 +13,20 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
roleBypassRLSAttr = "bypass_row_level_security"
|
||||
roleConnLimitAttr = "connection_limit"
|
||||
roleCreateDBAttr = "create_database"
|
||||
roleCreateRoleAttr = "create_role"
|
||||
roleEncryptedPassAttr = "encrypted_password"
|
||||
roleInheritAttr = "inherit"
|
||||
roleLoginAttr = "login"
|
||||
roleNameAttr = "name"
|
||||
rolePasswordAttr = "password"
|
||||
roleReplicationAttr = "replication"
|
||||
roleSuperuserAttr = "superuser"
|
||||
roleValidUntilAttr = "valid_until"
|
||||
roleBypassRLSAttr = "bypass_row_level_security"
|
||||
roleConnLimitAttr = "connection_limit"
|
||||
roleCreateDBAttr = "create_database"
|
||||
roleCreateRoleAttr = "create_role"
|
||||
roleEncryptedPassAttr = "encrypted_password"
|
||||
roleInheritAttr = "inherit"
|
||||
roleLoginAttr = "login"
|
||||
roleNameAttr = "name"
|
||||
rolePasswordAttr = "password"
|
||||
roleReplicationAttr = "replication"
|
||||
roleSkipDropRoleAttr = "skip_drop_role"
|
||||
roleSkipReassignOwnedAttr = "skip_reassign_owned"
|
||||
roleSuperuserAttr = "superuser"
|
||||
roleValidUntilAttr = "valid_until"
|
||||
|
||||
// Deprecated options
|
||||
roleDepEncryptedAttr = "encrypted"
|
||||
|
@ -120,6 +122,18 @@ func resourcePostgreSQLRole() *schema.Resource {
|
|||
Default: false,
|
||||
Description: "Determine whether a role bypasses every row-level security (RLS) policy",
|
||||
},
|
||||
roleSkipDropRoleAttr: {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "Skip actually running the DROP ROLE command when removing a ROLE from PostgreSQL",
|
||||
},
|
||||
roleSkipReassignOwnedAttr: {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "Skip actually running the REASSIGN OWNED command when removing a role from PostgreSQL",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -240,11 +254,35 @@ func resourcePostgreSQLRoleDelete(d *schema.ResourceData, meta interface{}) erro
|
|||
}
|
||||
defer conn.Close()
|
||||
|
||||
roleName := d.Get(roleNameAttr).(string)
|
||||
query := fmt.Sprintf("DROP ROLE %s", pq.QuoteIdentifier(roleName))
|
||||
_, err = conn.Query(query)
|
||||
txn, err := conn.Begin()
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Error deleting role: {{err}}", err)
|
||||
return err
|
||||
}
|
||||
defer txn.Rollback()
|
||||
|
||||
roleName := d.Get(roleNameAttr).(string)
|
||||
|
||||
queries := make([]string, 0, 3)
|
||||
if !d.Get(roleSkipReassignOwnedAttr).(bool) {
|
||||
queries = append(queries, fmt.Sprintf("REASSIGN OWNED BY %s TO CURRENT_USER", pq.QuoteIdentifier(roleName)))
|
||||
queries = append(queries, fmt.Sprintf("DROP OWNED BY %s", pq.QuoteIdentifier(roleName)))
|
||||
}
|
||||
|
||||
if !d.Get(roleSkipDropRoleAttr).(bool) {
|
||||
queries = append(queries, fmt.Sprintf("DROP ROLE %s", pq.QuoteIdentifier(roleName)))
|
||||
}
|
||||
|
||||
if len(queries) > 0 {
|
||||
for _, query := range queries {
|
||||
_, err = conn.Query(query)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Error deleting role: {{err}}", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := txn.Commit(); err != nil {
|
||||
return errwrap.Wrapf("Error committing schema: {{err}}", err)
|
||||
}
|
||||
}
|
||||
|
||||
d.SetId("")
|
||||
|
@ -282,6 +320,8 @@ func resourcePostgreSQLRoleRead(d *schema.ResourceData, meta interface{}) error
|
|||
d.Set(roleInheritAttr, roleInherit)
|
||||
d.Set(roleLoginAttr, roleCanLogin)
|
||||
d.Set(roleReplicationAttr, roleReplication)
|
||||
d.Set(roleSkipDropRoleAttr, d.Get(roleSkipDropRoleAttr).(bool))
|
||||
d.Set(roleSkipReassignOwnedAttr, d.Get(roleSkipReassignOwnedAttr).(bool))
|
||||
d.Set(roleSuperuserAttr, roleSuperuser)
|
||||
d.Set(roleValidUntilAttr, roleValidUntil)
|
||||
d.SetId(roleName)
|
||||
|
|
|
@ -23,6 +23,10 @@ func TestAccPostgresqlRole_Basic(t *testing.T) {
|
|||
"postgresql_role.myrole2", "name", "myrole2"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"postgresql_role.myrole2", "login", "true"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"postgresql_role.myrole2", "skip_drop_role", "false"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"postgresql_role.myrole2", "skip_reassign_owned", "false"),
|
||||
|
||||
resource.TestCheckResourceAttr(
|
||||
"postgresql_role.role_with_defaults", "name", "testing_role_with_defaults"),
|
||||
|
@ -46,6 +50,10 @@ func TestAccPostgresqlRole_Basic(t *testing.T) {
|
|||
"postgresql_role.role_with_defaults", "password", ""),
|
||||
resource.TestCheckResourceAttr(
|
||||
"postgresql_role.role_with_defaults", "valid_until", "infinity"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"postgresql_role.role_with_defaults", "skip_drop_role", "false"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"postgresql_role.role_with_defaults", "skip_reassign_owned", "false"),
|
||||
),
|
||||
},
|
||||
},
|
||||
|
@ -164,6 +172,8 @@ resource "postgresql_role" "role_with_defaults" {
|
|||
connection_limit = -1
|
||||
encrypted_password = true
|
||||
password = ""
|
||||
skip_drop_role = false
|
||||
skip_reassign_owned = false
|
||||
valid_until = "infinity"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -11,6 +11,15 @@ description: |-
|
|||
The ``postgresql_role`` resource creates and manages a role on a PostgreSQL
|
||||
server.
|
||||
|
||||
When a ``postgresql_role`` resource is removed, the PostgreSQL ROLE will
|
||||
automatically run a [`REASSIGN
|
||||
OWNED`](https://www.postgresql.org/docs/current/static/sql-reassign-owned.html)
|
||||
and [`DROP
|
||||
OWNED`](https://www.postgresql.org/docs/current/static/sql-drop-owned.html) to
|
||||
the `CURRENT_USER` (normally the connected user for the provider). If the
|
||||
specified PostgreSQL ROLE owns objects in multiple PostgreSQL databases in the
|
||||
same PostgreSQL Cluster, one PostgreSQL provider per database must be created
|
||||
and all but the final ``postgresql_role`` must specify a `skip_drop_role`.
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -82,6 +91,23 @@ resource "postgresql_role" "my_replication_role" {
|
|||
datetime. If omitted or the magic value `NULL` is used, `valid_until` will be
|
||||
set to `infinity`. Default is `NULL`, therefore `infinity`.
|
||||
|
||||
* `skip_drop_role` - (Optional) When a PostgreSQL ROLE exists in multiple
|
||||
databases and the ROLE is dropped, the
|
||||
[cleanup of ownership of objects](https://www.postgresql.org/docs/current/static/role-removal.html)
|
||||
in each of the respective databases must occur before the ROLE can be dropped
|
||||
from the catalog. Set this option to true when there are multiple databases
|
||||
in a PostgreSQL cluster using the same PostgreSQL ROLE for object ownership.
|
||||
This is the third and final step taken when removing a ROLE from a database.
|
||||
|
||||
* `skip_reassign_owned` - (Optional) When a PostgreSQL ROLE exists in multiple
|
||||
databases and the ROLE is dropped, a
|
||||
[`REASSIGN OWNED`](https://www.postgresql.org/docs/current/static/sql-reassign-owned.html) in
|
||||
must be executed on each of the respective databases before the `DROP ROLE`
|
||||
can be executed to dropped the ROLE from the catalog. This is the first and
|
||||
second steps taken when removing a ROLE from a database (the second step being
|
||||
an implicit
|
||||
[`DROP OWNED`](https://www.postgresql.org/docs/current/static/sql-drop-owned.html)).
|
||||
|
||||
## Import Example
|
||||
|
||||
`postgresql_role` supports importing resources. Supposing the following
|
||||
|
|
Loading…
Reference in New Issue