Skip to content

Commit 84ad984

Browse files
committed
feat: Add postgresql_security_label resource
1 parent f7fc45b commit 84ad984

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

postgresql/resource_postgresql_security_label.go

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"database/sql"
66
"fmt"
77
"log"
8+
"regexp"
89
"strings"
910

1011
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -24,6 +25,7 @@ func resourcePostgreSQLSecurityLabel() *schema.Resource {
2425
Read: PGResourceFunc(resourcePostgreSQLSecurityLabelRead),
2526
Update: PGResourceFunc(resourcePostgreSQLSecurityLabelUpdate),
2627
Delete: PGResourceFunc(resourcePostgreSQLSecurityLabelDelete),
28+
// Exists: PGResourceExistsFunc(resourcePostgreSQLSecurityLabelExists),
2729
Importer: &schema.ResourceImporter{
2830
StateContext: schema.ImportStatePassthroughContext,
2931
},
@@ -60,7 +62,7 @@ func resourcePostgreSQLSecurityLabel() *schema.Resource {
6062
func resourcePostgreSQLSecurityLabelCreate(db *DBConnection, d *schema.ResourceData) error {
6163
if !db.featureSupported(featureSecurityLabel) {
6264
return fmt.Errorf(
63-
"Security Label is not supported for this Postgres version (%s)",
65+
"security Label is not supported for this Postgres version (%s)",
6466
db.version,
6567
)
6668
}
@@ -75,6 +77,38 @@ func resourcePostgreSQLSecurityLabelCreate(db *DBConnection, d *schema.ResourceD
7577
return resourcePostgreSQLSecurityLabelReadImpl(db, d)
7678
}
7779

80+
// func resourcePostgreSQLSecurityLabelExists(db *DBConnection, d *schema.ResourceData) (bool, error) {
81+
// if !db.featureSupported(featureSecurityLabel) {
82+
// return false, fmt.Errorf(
83+
// "Security Label is not supported for this Postgres version (%s)",
84+
// db.version,
85+
// )
86+
// }
87+
// log.Printf("[WARN] PostgreSQL security label Exists")
88+
89+
// id := strings.Split(d.Id(), ".")
90+
// if len(id) != 3 {
91+
// return false, fmt.Errorf(
92+
// "Invalid ID: %s. ID should be in the format of %s.%s.%s",
93+
// d.Id(),
94+
// securityLabelProviderAttr,
95+
// securityLabelObjectTypeAttr,
96+
// securityLabelObjectNameAttr,
97+
// )
98+
// }
99+
100+
// provider := id[0]
101+
// objectType := id[1]
102+
// objectName := id[2]
103+
// query := "SELECT objtype FROM pg_seclabels WHERE objtype = $1 and objname = $2 and provider = $3"
104+
// err := db.QueryRow(query, objectType, quoteIdentifier(objectName), quoteIdentifier(provider)).Scan(&objectType)
105+
// if err == sql.ErrNoRows || err != nil {
106+
// return false, err
107+
// }
108+
109+
// return true, nil
110+
// }
111+
78112
func resourcePostgreSQLSecurityLabelUpdateImpl(db *DBConnection, d *schema.ResourceData, label string) error {
79113
b := bytes.NewBufferString("SECURITY LABEL ")
80114

@@ -115,11 +149,11 @@ func resourcePostgreSQLSecurityLabelReadImpl(db *DBConnection, d *schema.Resourc
115149
}
116150
defer deferredRollback(txn)
117151

118-
query := "SELECT objtype, objname, provider, label FROM pg_seclabels WHERE objtype = $1 and objname = $2 and provider = $3"
119-
row := db.QueryRow(query, objectType, objectName, provider)
152+
query := "SELECT objtype, provider, label FROM pg_seclabels WHERE objtype = $1 and objname = $2 and provider = $3"
153+
row := db.QueryRow(query, objectType, quoteIdentifier(objectName), quoteIdentifier(provider))
120154

121155
var label string
122-
err = row.Scan(&objectType, &objectName, &provider, &label)
156+
err = row.Scan(&objectType, &provider, &label)
123157
switch {
124158
case err == sql.ErrNoRows:
125159
log.Printf("[WARN] PostgreSQL security label for (%s '%s') with provider %s not found", objectType, objectName, provider)
@@ -180,3 +214,12 @@ func generateSecurityLabelID(d *schema.ResourceData) string {
180214
d.Get(securityLabelObjectNameAttr).(string),
181215
}, ".")
182216
}
217+
218+
func quoteIdentifier(s string) string {
219+
var result = s
220+
re := regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
221+
if !re.MatchString(s) || s != strings.ToLower(s) {
222+
result = pq.QuoteIdentifier(s)
223+
}
224+
return result
225+
}

postgresql/resource_postgresql_security_label_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestAccPostgresqlSecurityLabel_Update(t *testing.T) {
7575
Check: resource.ComposeTestCheckFunc(
7676
testAccCheckPostgresqlSecurityLabelExists("postgresql_security_label.test_label"),
7777
resource.TestCheckResourceAttr(
78-
"postgresql_security_label.test_label", "object_name", "security_label_test_role2"),
78+
"postgresql_security_label.test_label", "object_name", "security_label_test-role2"),
7979
),
8080
},
8181
},
@@ -84,7 +84,7 @@ func TestAccPostgresqlSecurityLabel_Update(t *testing.T) {
8484

8585
func checkSecurityLabelExists(txn *sql.Tx, objectType string, objectName string, provider string) (bool, error) {
8686
var _rez bool
87-
err := txn.QueryRow("SELECT TRUE FROM pg_seclabels WHERE objtype = $1 AND objname = $2 AND provider = $3", objectType, objectName, provider).Scan(&_rez)
87+
err := txn.QueryRow("SELECT TRUE FROM pg_seclabels WHERE objtype = $1 AND objname = $2 AND provider = $3", objectType, quoteIdentifier(objectName), provider).Scan(&_rez)
8888
switch {
8989
case err == sql.ErrNoRows:
9090
return false, nil
@@ -175,10 +175,10 @@ resource "postgresql_role" "test_role" {
175175
create_database = true
176176
}
177177
resource "postgresql_security_label" "test_label" {
178-
object_type = "role"
179-
object_name = postgresql_role.test_role.name
178+
object_type = "role"
179+
object_name = postgresql_role.test_role.name
180180
label_provider = "dummy"
181-
label = "secret"
181+
label = "secret"
182182
}
183183
`
184184

@@ -189,23 +189,23 @@ resource "postgresql_role" "test_role" {
189189
create_database = true
190190
}
191191
resource "postgresql_security_label" "test_label" {
192-
object_type = "role"
193-
object_name = postgresql_role.test_role.name
192+
object_type = "role"
193+
object_name = postgresql_role.test_role.name
194194
label_provider = "dummy"
195-
label = "top secret"
195+
label = "top secret"
196196
}
197197
`
198198

199199
var testAccPostgresqlSecurityLabelChanges3 = `
200200
resource "postgresql_role" "test_role" {
201-
name = "security_label_test_role2"
201+
name = "security_label_test-role2"
202202
login = true
203203
create_database = true
204204
}
205205
resource "postgresql_security_label" "test_label" {
206-
object_type = "role"
207-
object_name = postgresql_role.test_role.name
206+
object_type = "role"
207+
object_name = postgresql_role.test_role.name
208208
label_provider = "dummy"
209-
label = "top secret"
209+
label = "top secret"
210210
}
211211
`

website/docs/r/postgresql_security_label.html.markdown

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ resource "postgresql_security_label" "workload" {
3636
* `object_name` - (Required) The name of the object to be labeled. Names of objects that reside in schemas (tables, functions, etc.) can be schema-qualified.
3737
* `label_provider` - (Required) The name of the provider with which this label is to be associated.
3838
* `label` - (Required) The value of the security label.
39+
40+
## Import
41+
42+
Security label is an attribute that can be added multiple times, so no import is needed, simply apply again.

0 commit comments

Comments
 (0)