Skip to content

Commit 1c4bb78

Browse files
committed
Fix #321 replaces postgresql_grant all the time.
Based on doctolib's fork.
1 parent dea1401 commit 1c4bb78

File tree

2 files changed

+58
-37
lines changed

2 files changed

+58
-37
lines changed

postgresql/resource_postgresql_grant.go

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ var objectTypes = map[string]string{
3434
"schema": "n",
3535
}
3636

37+
type ResourceSchemeGetter func(string) interface{}
38+
3739
func resourcePostgreSQLGrant() *schema.Resource {
3840
return &schema.Resource{
3941
Create: PGResourceFunc(resourcePostgreSQLGrantCreate),
40-
// Since all of this resource's arguments force a recreation
41-
// there's no need for an Update function
42-
// Update:
42+
Update: PGResourceFunc(resourcePostgreSQLGrantUpdate),
4343
Read: PGResourceFunc(resourcePostgreSQLGrantRead),
4444
Delete: PGResourceFunc(resourcePostgreSQLGrantDelete),
4545

@@ -86,9 +86,9 @@ func resourcePostgreSQLGrant() *schema.Resource {
8686
Description: "The specific columns to grant privileges on for this role",
8787
},
8888
"privileges": {
89-
Type: schema.TypeSet,
90-
Required: true,
91-
ForceNew: true,
89+
Type: schema.TypeSet,
90+
Required: true,
91+
//ForceNew: true,
9292
Elem: &schema.Schema{Type: schema.TypeString},
9393
Set: schema.HashString,
9494
Description: "The list of privileges to grant",
@@ -129,6 +129,14 @@ func resourcePostgreSQLGrantRead(db *DBConnection, d *schema.ResourceData) error
129129
}
130130

131131
func resourcePostgreSQLGrantCreate(db *DBConnection, d *schema.ResourceData) error {
132+
return resourcePostgreSQLGrantCreateOrUpdate(db, d, false)
133+
}
134+
135+
func resourcePostgreSQLGrantUpdate(db *DBConnection, d *schema.ResourceData) error {
136+
return resourcePostgreSQLGrantCreateOrUpdate(db, d, true)
137+
}
138+
139+
func resourcePostgreSQLGrantCreateOrUpdate(db *DBConnection, d *schema.ResourceData, usePrevious bool) error {
132140
if err := validateFeatureSupport(db, d); err != nil {
133141
return fmt.Errorf("feature is not supported: %v", err)
134142
}
@@ -187,7 +195,7 @@ func resourcePostgreSQLGrantCreate(db *DBConnection, d *schema.ResourceData) err
187195
// Revoke all privileges before granting otherwise reducing privileges will not work.
188196
// We just have to revoke them in the same transaction so the role will not lost its
189197
// privileges between the revoke and grant statements.
190-
if err := revokeRolePrivileges(txn, d); err != nil {
198+
if err := revokeRolePrivileges(txn, d, usePrevious); err != nil {
191199
return err
192200
}
193201
if err := grantRolePrivileges(txn, d); err != nil {
@@ -243,7 +251,7 @@ func resourcePostgreSQLGrantDelete(db *DBConnection, d *schema.ResourceData) err
243251
}
244252

245253
if err := withRolesGranted(txn, owners, func() error {
246-
return revokeRolePrivileges(txn, d)
254+
return revokeRolePrivileges(txn, d, false)
247255
}); err != nil {
248256
return err
249257
}
@@ -589,40 +597,40 @@ func createGrantQuery(d *schema.ResourceData, privileges []string) string {
589597
return query
590598
}
591599

592-
func createRevokeQuery(d *schema.ResourceData) string {
600+
func createRevokeQuery(getter ResourceSchemeGetter) string {
593601
var query string
594602

595-
switch strings.ToUpper(d.Get("object_type").(string)) {
603+
switch strings.ToUpper(getter("object_type").(string)) {
596604
case "DATABASE":
597605
query = fmt.Sprintf(
598606
"REVOKE ALL PRIVILEGES ON DATABASE %s FROM %s",
599-
pq.QuoteIdentifier(d.Get("database").(string)),
600-
pq.QuoteIdentifier(d.Get("role").(string)),
607+
pq.QuoteIdentifier(getter("database").(string)),
608+
pq.QuoteIdentifier(getter("role").(string)),
601609
)
602610
case "SCHEMA":
603611
query = fmt.Sprintf(
604612
"REVOKE ALL PRIVILEGES ON SCHEMA %s FROM %s",
605-
pq.QuoteIdentifier(d.Get("schema").(string)),
606-
pq.QuoteIdentifier(d.Get("role").(string)),
613+
pq.QuoteIdentifier(getter("schema").(string)),
614+
pq.QuoteIdentifier(getter("role").(string)),
607615
)
608616
case "FOREIGN_DATA_WRAPPER":
609-
fdwName := d.Get("objects").(*schema.Set).List()[0]
617+
fdwName := getter("objects").(*schema.Set).List()[0]
610618
query = fmt.Sprintf(
611619
"REVOKE ALL PRIVILEGES ON FOREIGN DATA WRAPPER %s FROM %s",
612620
pq.QuoteIdentifier(fdwName.(string)),
613-
pq.QuoteIdentifier(d.Get("role").(string)),
621+
pq.QuoteIdentifier(getter("role").(string)),
614622
)
615623
case "FOREIGN_SERVER":
616-
srvName := d.Get("objects").(*schema.Set).List()[0]
624+
srvName := getter("objects").(*schema.Set).List()[0]
617625
query = fmt.Sprintf(
618626
"REVOKE ALL PRIVILEGES ON FOREIGN SERVER %s FROM %s",
619627
pq.QuoteIdentifier(srvName.(string)),
620-
pq.QuoteIdentifier(d.Get("role").(string)),
628+
pq.QuoteIdentifier(getter("role").(string)),
621629
)
622630
case "COLUMN":
623-
objects := d.Get("objects").(*schema.Set)
624-
columns := d.Get("columns").(*schema.Set)
625-
privileges := d.Get("privileges").(*schema.Set)
631+
objects := getter("objects").(*schema.Set)
632+
columns := getter("columns").(*schema.Set)
633+
privileges := getter("privileges").(*schema.Set)
626634
if privileges.Len() == 0 || columns.Len() == 0 {
627635
// No privileges to revoke, so don't revoke anything
628636
query = "SELECT NULL"
@@ -631,38 +639,38 @@ func createRevokeQuery(d *schema.ResourceData) string {
631639
"REVOKE %s (%s) ON TABLE %s FROM %s",
632640
setToPgIdentSimpleList(privileges),
633641
setToPgIdentListWithoutSchema(columns),
634-
setToPgIdentList(d.Get("schema").(string), objects),
635-
pq.QuoteIdentifier(d.Get("role").(string)),
642+
setToPgIdentList(getter("schema").(string), objects),
643+
pq.QuoteIdentifier(getter("role").(string)),
636644
)
637645
}
638646
case "TABLE", "SEQUENCE", "FUNCTION", "PROCEDURE", "ROUTINE":
639-
objects := d.Get("objects").(*schema.Set)
640-
privileges := d.Get("privileges").(*schema.Set)
647+
objects := getter("objects").(*schema.Set)
648+
privileges := getter("privileges").(*schema.Set)
641649
if objects.Len() > 0 {
642650
if privileges.Len() > 0 {
643651
// Revoking specific privileges instead of all privileges
644652
// to avoid messing with column level grants
645653
query = fmt.Sprintf(
646654
"REVOKE %s ON %s %s FROM %s",
647655
setToPgIdentSimpleList(privileges),
648-
strings.ToUpper(d.Get("object_type").(string)),
649-
setToPgIdentList(d.Get("schema").(string), objects),
650-
pq.QuoteIdentifier(d.Get("role").(string)),
656+
strings.ToUpper(getter("object_type").(string)),
657+
setToPgIdentList(getter("schema").(string), objects),
658+
pq.QuoteIdentifier(getter("role").(string)),
651659
)
652660
} else {
653661
query = fmt.Sprintf(
654662
"REVOKE ALL PRIVILEGES ON %s %s FROM %s",
655-
strings.ToUpper(d.Get("object_type").(string)),
656-
setToPgIdentList(d.Get("schema").(string), objects),
657-
pq.QuoteIdentifier(d.Get("role").(string)),
663+
strings.ToUpper(getter("object_type").(string)),
664+
setToPgIdentList(getter("schema").(string), objects),
665+
pq.QuoteIdentifier(getter("role").(string)),
658666
)
659667
}
660668
} else {
661669
query = fmt.Sprintf(
662670
"REVOKE ALL PRIVILEGES ON ALL %sS IN SCHEMA %s FROM %s",
663-
strings.ToUpper(d.Get("object_type").(string)),
664-
pq.QuoteIdentifier(d.Get("schema").(string)),
665-
pq.QuoteIdentifier(d.Get("role").(string)),
671+
strings.ToUpper(getter("object_type").(string)),
672+
pq.QuoteIdentifier(getter("schema").(string)),
673+
pq.QuoteIdentifier(getter("role").(string)),
666674
)
667675
}
668676
}
@@ -687,8 +695,21 @@ func grantRolePrivileges(txn *sql.Tx, d *schema.ResourceData) error {
687695
return err
688696
}
689697

690-
func revokeRolePrivileges(txn *sql.Tx, d *schema.ResourceData) error {
691-
query := createRevokeQuery(d)
698+
func revokeRolePrivileges(txn *sql.Tx, d *schema.ResourceData, usePrevious bool) error {
699+
getter := d.Get
700+
701+
if usePrevious {
702+
getter = func(name string) interface{} {
703+
if d.HasChange(name) {
704+
old, _ := d.GetChange(name)
705+
return old
706+
}
707+
708+
return d.Get(name)
709+
}
710+
}
711+
712+
query := createRevokeQuery(getter)
692713
if len(query) == 0 {
693714
// Query is empty, don't run anything
694715
return nil

postgresql/resource_postgresql_grant_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ func TestCreateRevokeQuery(t *testing.T) {
293293
}
294294

295295
for _, c := range cases {
296-
out := createRevokeQuery(c.resource)
296+
out := createRevokeQuery(c.resource.Get)
297297
if out != c.expected {
298298
t.Fatalf("Error matching output and expected: %#v vs %#v", out, c.expected)
299299
}

0 commit comments

Comments
 (0)