From d7918bbfad6040d54a244c7e21db9404f978a9b1 Mon Sep 17 00:00:00 2001 From: Siva Manivannan Date: Mon, 27 Apr 2020 21:17:57 -0500 Subject: [PATCH 1/5] init --- postgresql/resource_postgresql_role.go | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/postgresql/resource_postgresql_role.go b/postgresql/resource_postgresql_role.go index 98c34f04..c3ed41c6 100644 --- a/postgresql/resource_postgresql_role.go +++ b/postgresql/resource_postgresql_role.go @@ -24,6 +24,7 @@ const ( roleEncryptedPassAttr = "encrypted_password" roleInheritAttr = "inherit" roleLoginAttr = "login" + roleLogStatementAttr = "log_statement" roleNameAttr = "name" rolePasswordAttr = "password" roleReplicationAttr = "replication" @@ -39,6 +40,13 @@ const ( roleDepEncryptedAttr = "encrypted" ) +var allowedLogStatementOpts = []string{ + "none", + "ddl", + "mod", + "all", +} + func resourcePostgreSQLRole() *schema.Resource { return &schema.Resource{ Create: resourcePostgreSQLRoleCreate, @@ -131,6 +139,13 @@ func resourcePostgreSQLRole() *schema.Resource { Default: false, Description: "Determine whether a role is allowed to log in", }, + roleLogStatementAttr: { + Type: schema.TypeString, + Optional: true, + Default: "none", + ValidateFunc: validation.StringInSlice(allowedLogStatementOpts, false), + Description: "Sets the log level for SQL statements", + }, roleReplicationAttr: { Type: schema.TypeBool, Optional: true, @@ -789,6 +804,22 @@ func setRoleLogin(txn *sql.Tx, d *schema.ResourceData) error { return nil } +func setRoleLogStatement(txn *sql.Tx, d *schema.ResourceData) error { + if !d.HasChange(roleLogStatementAttr) { + return nil + } + + level := d.Get(roleLogStatementAttr).(string) + + roleName := d.Get(roleNameAttr).(string) + sql := fmt.Sprintf("ALTER ROLE %s SET log_statement TO %s", pq.QuoteIdentifier(roleName), level) + if _, err := txn.Exec(sql); err != nil { + return errwrap.Wrapf("Error updating role log_statement: {{err}}", err) + } + + return nil +} + func setRoleReplication(txn *sql.Tx, d *schema.ResourceData) error { if !d.HasChange(roleReplicationAttr) { return nil From be91af186bb385e35c41e3e8a1f4c38a5ed48d0d Mon Sep 17 00:00:00 2001 From: Siva Manivannan Date: Mon, 27 Apr 2020 22:21:54 -0500 Subject: [PATCH 2/5] add read for log_statement --- postgresql/resource_postgresql_role.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/postgresql/resource_postgresql_role.go b/postgresql/resource_postgresql_role.go index c3ed41c6..7799b87a 100644 --- a/postgresql/resource_postgresql_role.go +++ b/postgresql/resource_postgresql_role.go @@ -310,6 +310,10 @@ func resourcePostgreSQLRoleCreate(d *schema.ResourceData, meta interface{}) erro return err } + if err = setRoleLogStatement(txn, d); err != nil { + return err + } + if err = txn.Commit(); err != nil { return errwrap.Wrapf("could not commit transaction: {{err}}", err) } @@ -464,6 +468,7 @@ func resourcePostgreSQLRoleReadImpl(c *Client, d *schema.ResourceData) error { d.Set(roleReplicationAttr, roleBypassRLS) d.Set(roleRolesAttr, pgArrayToSet(roleRoles)) d.Set(roleSearchPathAttr, readSearchPath(roleConfig)) + d.Set(roleLogStatementAttr, readLogStatement(roleConfig, d.Get(roleLogStatementAttr).(string))) statementTimeout, err := readStatementTimeout(roleConfig) if err != nil { @@ -496,6 +501,19 @@ func readSearchPath(roleConfig pq.ByteaArray) []string { return nil } +// readLogStatement searches for a log_statement entry in the rolconfig array. +// In case no such value is present, it returns empty. +func readLogStatement(roleConfig pq.ByteaArray, defaultValue string) string { + for _, v := range roleConfig { + config := string(v) + if strings.HasPrefix(config, roleLogStatementAttr) { + var result = strings.TrimPrefix(config, roleLogStatementAttr+"=") + return result + } + } + return defaultValue +} + // readStatementTimeout searches for a statement_timeout entry in the rolconfig array. // In case no such value is present, it returns nil. func readStatementTimeout(roleConfig pq.ByteaArray) (int, error) { @@ -615,6 +633,10 @@ func resourcePostgreSQLRoleUpdate(d *schema.ResourceData, meta interface{}) erro return err } + if err := setRoleLogStatement(txn, d); err != nil { + return err + } + if err := setRoleReplication(txn, d); err != nil { return err } @@ -812,7 +834,7 @@ func setRoleLogStatement(txn *sql.Tx, d *schema.ResourceData) error { level := d.Get(roleLogStatementAttr).(string) roleName := d.Get(roleNameAttr).(string) - sql := fmt.Sprintf("ALTER ROLE %s SET log_statement TO %s", pq.QuoteIdentifier(roleName), level) + sql := fmt.Sprintf("ALTER ROLE %s SET log_statement TO %s", pq.QuoteIdentifier(roleName), pq.QuoteIdentifier(level)) if _, err := txn.Exec(sql); err != nil { return errwrap.Wrapf("Error updating role log_statement: {{err}}", err) } From 6710621cadf2928ef9a134b0c10d064b140ed79b Mon Sep 17 00:00:00 2001 From: Siva Manivannan Date: Tue, 28 Apr 2020 13:00:16 -0500 Subject: [PATCH 3/5] test updated --- postgresql/resource_postgresql_role_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/postgresql/resource_postgresql_role_test.go b/postgresql/resource_postgresql_role_test.go index 9b361c06..43a60a3b 100644 --- a/postgresql/resource_postgresql_role_test.go +++ b/postgresql/resource_postgresql_role_test.go @@ -37,6 +37,7 @@ func TestAccPostgresqlRole_Basic(t *testing.T) { resource.TestCheckResourceAttr("postgresql_role.role_with_defaults", "inherit", "false"), resource.TestCheckResourceAttr("postgresql_role.role_with_defaults", "replication", "false"), resource.TestCheckResourceAttr("postgresql_role.role_with_defaults", "bypass_row_level_security", "false"), + resource.TestCheckResourceAttr("postgresql_role.role_with_defaults", "log_statement", "none"), resource.TestCheckResourceAttr("postgresql_role.role_with_defaults", "connection_limit", "-1"), resource.TestCheckResourceAttr("postgresql_role.role_with_defaults", "encrypted_password", "true"), resource.TestCheckResourceAttr("postgresql_role.role_with_defaults", "password", ""), @@ -322,6 +323,7 @@ resource "postgresql_role" "role_with_defaults" { login = false replication = false bypass_row_level_security = false + log_statement = "none" connection_limit = -1 encrypted_password = true password = "" From fba6ca20714c02503acecf5586b966319c45c152 Mon Sep 17 00:00:00 2001 From: Siva Manivannan Date: Tue, 28 Apr 2020 13:45:03 -0500 Subject: [PATCH 4/5] update docs --- website/docs/r/postgresql_role.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/r/postgresql_role.html.markdown b/website/docs/r/postgresql_role.html.markdown index 97df8cb8..c034f047 100644 --- a/website/docs/r/postgresql_role.html.markdown +++ b/website/docs/r/postgresql_role.html.markdown @@ -116,6 +116,8 @@ resource "postgresql_role" "my_replication_role" { * `statement_timeout` - (Optional) Defines [`statement_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#RUNTIME-CONFIG-CLIENT-STATEMENT) setting for this role which allows to abort any statement that takes more than the specified amount of time. +* `log_statement` - (Optional) Defines [`log_statement`](https://www.postgresql.org/docs/current/runtime-config-logging.html) setting for this role which controls the type of SQL statements that are logged. Default is `none` + ## Import Example `postgresql_role` supports importing resources. Supposing the following From 1af8c0ae9c205e631f6a5669665e1c7f654f73c0 Mon Sep 17 00:00:00 2001 From: Siva Manivannan Date: Tue, 28 Apr 2020 13:54:18 -0500 Subject: [PATCH 5/5] update tests for log_statement --- postgresql/resource_postgresql_role_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/postgresql/resource_postgresql_role_test.go b/postgresql/resource_postgresql_role_test.go index 43a60a3b..2ab55c91 100644 --- a/postgresql/resource_postgresql_role_test.go +++ b/postgresql/resource_postgresql_role_test.go @@ -91,6 +91,7 @@ resource "postgresql_role" "update_role" { roles = ["${postgresql_role.group_role.name}"] search_path = ["mysearchpath"] statement_timeout = 30000 + log_statement = "all" } ` resource.Test(t, resource.TestCase{ @@ -113,6 +114,7 @@ resource "postgresql_role" "update_role" { resource.TestCheckResourceAttr("postgresql_role.update_role", "roles.#", "0"), resource.TestCheckResourceAttr("postgresql_role.update_role", "search_path.#", "0"), resource.TestCheckResourceAttr("postgresql_role.update_role", "statement_timeout", "0"), + resource.TestCheckResourceAttr("postgresql_role.update_role", "log_statement", "none"), testAccCheckRoleCanLogin(t, "update_role", "toto"), ), }, @@ -135,6 +137,7 @@ resource "postgresql_role" "update_role" { resource.TestCheckResourceAttr("postgresql_role.update_role", "search_path.#", "1"), resource.TestCheckResourceAttr("postgresql_role.update_role", "search_path.0", "mysearchpath"), resource.TestCheckResourceAttr("postgresql_role.update_role", "statement_timeout", "30000"), + resource.TestCheckResourceAttr("postgresql_role.update_role", "log_statement", "all"), testAccCheckRoleCanLogin(t, "update_role2", "titi"), ), }, @@ -151,6 +154,7 @@ resource "postgresql_role" "update_role" { resource.TestCheckResourceAttr("postgresql_role.update_role", "roles.#", "0"), resource.TestCheckResourceAttr("postgresql_role.update_role", "search_path.#", "0"), resource.TestCheckResourceAttr("postgresql_role.update_role", "statement_timeout", "0"), + resource.TestCheckResourceAttr("postgresql_role.update_role", "log_statement", "none"), testAccCheckRoleCanLogin(t, "update_role", "toto"), ), },