diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7fe93374..dd788446 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - pgversion: [15, 14, 13, 12, 11] + pgversion: [16, 15, 14, 13, 12, 11] env: PGVERSION: ${{ matrix.pgversion }} diff --git a/examples/issues/407/test.tf b/examples/issues/407/test.tf new file mode 100644 index 00000000..286a83c1 --- /dev/null +++ b/examples/issues/407/test.tf @@ -0,0 +1,12 @@ +resource "postgresql_role" "this" { + name = "test" + login = true + password = "test" +} + +resource "postgresql_database" "this" { + name = "test" + owner = postgresql_role.this.name + lc_collate = "en_US.utf8" + allow_connections = true +} diff --git a/examples/issues/407/versions.tf b/examples/issues/407/versions.tf new file mode 120000 index 00000000..8bd0ff14 --- /dev/null +++ b/examples/issues/407/versions.tf @@ -0,0 +1 @@ +../versions.tf \ No newline at end of file diff --git a/postgresql/config.go b/postgresql/config.go index 17668c0e..0b225323 100644 --- a/postgresql/config.go +++ b/postgresql/config.go @@ -44,6 +44,7 @@ const ( featurePubWithoutTruncate featureFunction featureServer + featureCreateRoleSelfGrant ) var ( @@ -115,6 +116,10 @@ var ( featureServer: semver.MustParseRange(">=10.0.0"), featureDatabaseOwnerRole: semver.MustParseRange(">=15.0.0"), + + // New privileges rules in version 16 + // https://www.postgresql.org/docs/16/release-16.html#RELEASE-16-PRIVILEGES + featureCreateRoleSelfGrant: semver.MustParseRange(">=16.0.0"), } ) diff --git a/postgresql/helpers.go b/postgresql/helpers.go index f74f0b78..058da49d 100644 --- a/postgresql/helpers.go +++ b/postgresql/helpers.go @@ -56,11 +56,25 @@ func pqQuoteLiteral(in string) string { func isMemberOfRole(db QueryAble, role, member string) (bool, error) { var _rez int + setOption := true + err := db.QueryRow( - "SELECT 1 FROM pg_auth_members WHERE pg_get_userbyid(roleid) = $1 AND pg_get_userbyid(member) = $2", - role, member, + "SELECT 1 FROM information_schema.columns WHERE table_name='pg_auth_members' AND column_name = 'set_option'", ).Scan(&_rez) + switch { + case err == sql.ErrNoRows: + setOption = false + case err != nil: + return false, fmt.Errorf("could not read setOption column: %w", err) + } + + query := "SELECT 1 FROM pg_auth_members WHERE pg_get_userbyid(roleid) = $1 AND pg_get_userbyid(member) = $2" + if setOption { + query += " AND set_option" + } + + err = db.QueryRow(query, role, member).Scan(&_rez) switch { case err == sql.ErrNoRows: return false, nil diff --git a/postgresql/resource_postgresql_database_test.go b/postgresql/resource_postgresql_database_test.go index 0ac97445..f49ae1aa 100644 --- a/postgresql/resource_postgresql_database_test.go +++ b/postgresql/resource_postgresql_database_test.go @@ -346,17 +346,18 @@ func checkUserMembership( t *testing.T, dsn, member, role string, shouldHaveRole bool, ) resource.TestCheckFunc { return func(s *terraform.State) error { - db, err := sql.Open("postgres", dsn) + client := testAccProvider.Meta().(*Client) + db, err := client.Connect() if err != nil { t.Fatalf("could to create connection pool: %v", err) } - defer db.Close() var _rez int - err = db.QueryRow(` - SELECT 1 FROM pg_auth_members - WHERE pg_get_userbyid(roleid) = $1 AND pg_get_userbyid(member) = $2 - `, role, member).Scan(&_rez) + query := "SELECT 1 FROM pg_auth_members WHERE pg_get_userbyid(roleid) = $1 AND pg_get_userbyid(member) = $2" + if db.featureSupported(featureCreateRoleSelfGrant) { + query += " AND (set_option OR inherit_option)" + } + err = db.QueryRow(query, role, member).Scan(&_rez) switch { case err == sql.ErrNoRows: diff --git a/postgresql/resource_postgresql_role_test.go b/postgresql/resource_postgresql_role_test.go index ef502f00..fc958840 100644 --- a/postgresql/resource_postgresql_role_test.go +++ b/postgresql/resource_postgresql_role_test.go @@ -212,7 +212,16 @@ resource "postgresql_role" "test_role" { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) - testCheckCompatibleVersion(t, featurePrivileges) + client := testAccProvider.Meta().(*Client) + db, err := client.Connect() + if err != nil { + t.Fatalf("could connect to database: %v", err) + } + // Requires >= 9 and <16 + // We disable this test for >= pg16 as it makes no sense with the new createRoleSelfGrant feature + if !db.featureSupported(featurePrivileges) || db.featureSupported(featureCreateRoleSelfGrant) { + t.Skipf("Skip extension tests for Postgres %s", db.version) + } }, Providers: testAccProviders, CheckDestroy: testAccCheckPostgresqlRoleDestroy,