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
|
@ -23,6 +23,8 @@ const (
|
||||||
roleNameAttr = "name"
|
roleNameAttr = "name"
|
||||||
rolePasswordAttr = "password"
|
rolePasswordAttr = "password"
|
||||||
roleReplicationAttr = "replication"
|
roleReplicationAttr = "replication"
|
||||||
|
roleSkipDropRoleAttr = "skip_drop_role"
|
||||||
|
roleSkipReassignOwnedAttr = "skip_reassign_owned"
|
||||||
roleSuperuserAttr = "superuser"
|
roleSuperuserAttr = "superuser"
|
||||||
roleValidUntilAttr = "valid_until"
|
roleValidUntilAttr = "valid_until"
|
||||||
|
|
||||||
|
@ -120,6 +122,18 @@ func resourcePostgreSQLRole() *schema.Resource {
|
||||||
Default: false,
|
Default: false,
|
||||||
Description: "Determine whether a role bypasses every row-level security (RLS) policy",
|
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,12 +254,36 @@ func resourcePostgreSQLRoleDelete(d *schema.ResourceData, meta interface{}) erro
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
txn, err := conn.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer txn.Rollback()
|
||||||
|
|
||||||
roleName := d.Get(roleNameAttr).(string)
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
query := fmt.Sprintf("DROP ROLE %s", pq.QuoteIdentifier(roleName))
|
|
||||||
|
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)
|
_, err = conn.Query(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf("Error deleting role: {{err}}", err)
|
return errwrap.Wrapf("Error deleting role: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := txn.Commit(); err != nil {
|
||||||
|
return errwrap.Wrapf("Error committing schema: {{err}}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
|
|
||||||
|
@ -282,6 +320,8 @@ func resourcePostgreSQLRoleRead(d *schema.ResourceData, meta interface{}) error
|
||||||
d.Set(roleInheritAttr, roleInherit)
|
d.Set(roleInheritAttr, roleInherit)
|
||||||
d.Set(roleLoginAttr, roleCanLogin)
|
d.Set(roleLoginAttr, roleCanLogin)
|
||||||
d.Set(roleReplicationAttr, roleReplication)
|
d.Set(roleReplicationAttr, roleReplication)
|
||||||
|
d.Set(roleSkipDropRoleAttr, d.Get(roleSkipDropRoleAttr).(bool))
|
||||||
|
d.Set(roleSkipReassignOwnedAttr, d.Get(roleSkipReassignOwnedAttr).(bool))
|
||||||
d.Set(roleSuperuserAttr, roleSuperuser)
|
d.Set(roleSuperuserAttr, roleSuperuser)
|
||||||
d.Set(roleValidUntilAttr, roleValidUntil)
|
d.Set(roleValidUntilAttr, roleValidUntil)
|
||||||
d.SetId(roleName)
|
d.SetId(roleName)
|
||||||
|
|
|
@ -23,6 +23,10 @@ func TestAccPostgresqlRole_Basic(t *testing.T) {
|
||||||
"postgresql_role.myrole2", "name", "myrole2"),
|
"postgresql_role.myrole2", "name", "myrole2"),
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr(
|
||||||
"postgresql_role.myrole2", "login", "true"),
|
"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(
|
resource.TestCheckResourceAttr(
|
||||||
"postgresql_role.role_with_defaults", "name", "testing_role_with_defaults"),
|
"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", ""),
|
"postgresql_role.role_with_defaults", "password", ""),
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr(
|
||||||
"postgresql_role.role_with_defaults", "valid_until", "infinity"),
|
"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
|
connection_limit = -1
|
||||||
encrypted_password = true
|
encrypted_password = true
|
||||||
password = ""
|
password = ""
|
||||||
|
skip_drop_role = false
|
||||||
|
skip_reassign_owned = false
|
||||||
valid_until = "infinity"
|
valid_until = "infinity"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -11,6 +11,15 @@ description: |-
|
||||||
The ``postgresql_role`` resource creates and manages a role on a PostgreSQL
|
The ``postgresql_role`` resource creates and manages a role on a PostgreSQL
|
||||||
server.
|
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
|
## 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
|
datetime. If omitted or the magic value `NULL` is used, `valid_until` will be
|
||||||
set to `infinity`. Default is `NULL`, therefore `infinity`.
|
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
|
## Import Example
|
||||||
|
|
||||||
`postgresql_role` supports importing resources. Supposing the following
|
`postgresql_role` supports importing resources. Supposing the following
|
||||||
|
|
Loading…
Reference in New Issue