Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SESSION TIMEOUT support and missing defer rows.Close() #101

Merged
merged 2 commits into from
Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion redshift/data_source_redshift_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,17 @@ This data source can be used to fetch information about a specific database user
Computed: true,
Description: `Indicates whether the user is a superuser with all database privileges.`,
},
userSessionTimeoutAttr: {
Type: schema.TypeInt,
Computed: true,
Description: "The maximum time in seconds that a session remains inactive or idle. The range is 60 seconds (one minute) to 1,728,000 seconds (20 days). If no session timeout is set for the user, the cluster setting applies.",
},
},
}
}

func dataSourceRedshiftUserRead(db *DBConnection, d *schema.ResourceData) error {
var useSysID, userValidUntil, userConnLimit, userSyslogAccess string
var useSysID, userValidUntil, userConnLimit, userSyslogAccess, userSessionTimeout string
var userSuperuser, userCreateDB bool

columns := []string{
Expand All @@ -66,6 +71,7 @@ func dataSourceRedshiftUserRead(db *DBConnection, d *schema.ResourceData) error
"usesuper",
"syslogaccess",
`COALESCE(useconnlimit::TEXT, 'UNLIMITED')`,
"sessiontimeout",
}

values := []interface{}{
Expand All @@ -74,6 +80,7 @@ func dataSourceRedshiftUserRead(db *DBConnection, d *schema.ResourceData) error
&userSuperuser,
&userSyslogAccess,
&userConnLimit,
&userSessionTimeout,
}

userName := d.Get(userNameAttr).(string)
Expand All @@ -96,12 +103,18 @@ func dataSourceRedshiftUserRead(db *DBConnection, d *schema.ResourceData) error
}
}

userSessionTimeoutNumber, err := strconv.Atoi(userSessionTimeout)
if err != nil {
return err
}

d.SetId(useSysID)
d.Set(userCreateDBAttr, userCreateDB)
d.Set(userSuperuserAttr, userSuperuser)
d.Set(userSyslogAccessAttr, userSyslogAccess)
d.Set(userConnLimitAttr, userConnLimitNumber)
d.Set(userValidUntilAttr, userValidUntil)
d.Set(userSessionTimeoutAttr, userSessionTimeoutNumber)

return nil
}
1 change: 1 addition & 0 deletions redshift/data_source_redshift_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func TestAccDataSourceRedshiftUser_Basic(t *testing.T) {
resource.TestCheckResourceAttrSet("data.redshift_user.simple", userConnLimitAttr),
resource.TestCheckResourceAttrSet("data.redshift_user.simple", userSyslogAccessAttr),
resource.TestCheckResourceAttrSet("data.redshift_user.simple", userSuperuserAttr),
resource.TestCheckResourceAttrSet("data.redshift_user.simple", userSessionTimeoutAttr),
),
},
},
Expand Down
10 changes: 10 additions & 0 deletions redshift/resource_redshift_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ func readSchemaGrants(db *DBConnection, d *schema.ResourceData) error {
}

func readTableGrants(db *DBConnection, d *schema.ResourceData) error {
log.Printf("[DEBUG] Reading table grants")
var entityName, query string
_, isUser := d.GetOk(grantUserAttr)

Expand Down Expand Up @@ -344,6 +345,7 @@ func readTableGrants(db *DBConnection, d *schema.ResourceData) error {
if err != nil {
return err
}
defer rows.Close()

for rows.Next() {
var objName string
Expand Down Expand Up @@ -388,11 +390,14 @@ func readTableGrants(db *DBConnection, d *schema.ResourceData) error {
break
}
}
log.Printf("[DEBUG] Collected table grants")

return nil
}

func readCallableGrants(db *DBConnection, d *schema.ResourceData) error {
log.Printf("[DEBUG] Reading callable grants")

var entityName, query string

_, isUser := d.GetOk(grantUserAttr)
Expand Down Expand Up @@ -444,6 +449,7 @@ func readCallableGrants(db *DBConnection, d *schema.ResourceData) error {
}
return false
}
defer rows.Close()

privilegesSet := schema.NewSet(schema.HashString, nil)
for rows.Next() {
Expand All @@ -465,11 +471,13 @@ func readCallableGrants(db *DBConnection, d *schema.ResourceData) error {
if !privilegesSet.Equal(d.Get(grantPrivilegesAttr).(*schema.Set)) {
d.Set(grantPrivilegesAttr, privilegesSet)
}
log.Printf("[DEBUG] Reading callable grants - Done")

return nil
}

func readLanguageGrants(db *DBConnection, d *schema.ResourceData) error {
log.Printf("[DEBUG] Reading language grants")

var entityName, query string

Expand Down Expand Up @@ -503,6 +511,7 @@ func readLanguageGrants(db *DBConnection, d *schema.ResourceData) error {
}

objects := d.Get(grantObjectsAttr).(*schema.Set)
defer rows.Close()

for rows.Next() {
var objName string
Expand All @@ -526,6 +535,7 @@ func readLanguageGrants(db *DBConnection, d *schema.ResourceData) error {
break
}
}
log.Printf("[DEBUG] Reading language grants - Done")

return nil
}
Expand Down
61 changes: 52 additions & 9 deletions redshift/resource_redshift_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ import (
)

const (
userNameAttr = "name"
userPasswordAttr = "password"
userValidUntilAttr = "valid_until"
userCreateDBAttr = "create_database"
userConnLimitAttr = "connection_limit"
userSyslogAccessAttr = "syslog_access"
userSuperuserAttr = "superuser"
userNameAttr = "name"
userPasswordAttr = "password"
userValidUntilAttr = "valid_until"
userCreateDBAttr = "create_database"
userConnLimitAttr = "connection_limit"
userSyslogAccessAttr = "syslog_access"
userSuperuserAttr = "superuser"
userSessionTimeoutAttr = "session_timeout"

// defaults
defaultUserSyslogAccess = "RESTRICTED"
Expand Down Expand Up @@ -123,6 +124,13 @@ Amazon Redshift user accounts can only be created and dropped by a database supe
Default: false,
Description: `Determine whether the user is a superuser with all database privileges.`,
},
userSessionTimeoutAttr: {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "The maximum time in seconds that a session remains inactive or idle. The range is 60 seconds (one minute) to 1,728,000 seconds (20 days). If no session timeout is set for the user, the cluster setting applies.",
ValidateFunc: validation.All(validation.IntAtLeast(60), validation.IntAtMost(1728000)),
},
},
}
}
Expand Down Expand Up @@ -162,6 +170,7 @@ func resourceRedshiftUserCreate(db *DBConnection, d *schema.ResourceData) error
sqlKey string
}{
{userConnLimitAttr, "CONNECTION LIMIT"},
{userSessionTimeoutAttr, "SESSION TIMEOUT"},
}

boolOpts := []struct {
Expand Down Expand Up @@ -215,7 +224,9 @@ func resourceRedshiftUserCreate(db *DBConnection, d *schema.ResourceData) error

for _, opt := range intOpts {
val := d.Get(opt.hclKey).(int)
createOpts = append(createOpts, fmt.Sprintf("%s %d", opt.sqlKey, val))
if opt.hclKey != userSessionTimeoutAttr && val != 0 {
createOpts = append(createOpts, fmt.Sprintf("%s %d", opt.sqlKey, val))
}
}

for _, opt := range boolOpts {
Expand Down Expand Up @@ -253,7 +264,7 @@ func resourceRedshiftUserRead(db *DBConnection, d *schema.ResourceData) error {
}

func resourceRedshiftUserReadImpl(db *DBConnection, d *schema.ResourceData) error {
var userName, userValidUntil, userConnLimit, userSyslogAccess string
var userName, userValidUntil, userConnLimit, userSyslogAccess, userSessionTimeout string
var userSuperuser, userCreateDB bool

columns := []string{
Expand All @@ -262,6 +273,7 @@ func resourceRedshiftUserReadImpl(db *DBConnection, d *schema.ResourceData) erro
"usesuper",
"syslogaccess",
`COALESCE(useconnlimit::TEXT, 'UNLIMITED')`,
"sessiontimeout",
}

values := []interface{}{
Expand All @@ -270,6 +282,7 @@ func resourceRedshiftUserReadImpl(db *DBConnection, d *schema.ResourceData) erro
&userSuperuser,
&userSyslogAccess,
&userConnLimit,
&userSessionTimeout,
}

useSysID := d.Id()
Expand Down Expand Up @@ -301,12 +314,18 @@ func resourceRedshiftUserReadImpl(db *DBConnection, d *schema.ResourceData) erro
}
}

userSessionTimeoutNumber, err := strconv.Atoi(userSessionTimeout)
if err != nil {
return err
}

d.Set(userNameAttr, userName)
d.Set(userCreateDBAttr, userCreateDB)
d.Set(userSuperuserAttr, userSuperuser)
d.Set(userSyslogAccessAttr, userSyslogAccess)
d.Set(userConnLimitAttr, userConnLimitNumber)
d.Set(userValidUntilAttr, userValidUntil)
d.Set(userSessionTimeoutAttr, userSessionTimeoutNumber)

return nil
}
Expand Down Expand Up @@ -451,6 +470,10 @@ func resourceRedshiftUserUpdate(db *DBConnection, d *schema.ResourceData) error
return err
}

if err := setUserSessionTimeout(tx, d); err != nil {
return err
}

if err := tx.Commit(); err != nil {
return fmt.Errorf("could not commit transaction: %w", err)
}
Expand Down Expand Up @@ -514,6 +537,26 @@ func setUserConnLimit(tx *sql.Tx, d *schema.ResourceData) error {
return nil
}

func setUserSessionTimeout(tx *sql.Tx, d *schema.ResourceData) error {
if !d.HasChange(userSessionTimeoutAttr) {
return nil
}

sessionTimeout := d.Get(userSessionTimeoutAttr).(int)
userName := d.Get(userNameAttr).(string)
sql := ""
if sessionTimeout == 0 {
sql = fmt.Sprintf("ALTER USER %s RESET SESSION TIMEOUT", pq.QuoteIdentifier(userName))
} else {
sql = fmt.Sprintf("ALTER USER %s SESSION TIMEOUT %d", pq.QuoteIdentifier(userName), sessionTimeout)
}
if _, err := tx.Exec(sql); err != nil {
return fmt.Errorf("Error updating user SESSION TIMEOUT: %w", err)
}

return nil
}

func setUserCreateDB(tx *sql.Tx, d *schema.ResourceData) error {
if !d.HasChange(userCreateDBAttr) {
return nil
Expand Down
11 changes: 11 additions & 0 deletions redshift/resource_redshift_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func TestAccRedshiftUser_Basic(t *testing.T) {
resource.TestCheckResourceAttr("redshift_user.user_with_defaults", "password", ""),
resource.TestCheckResourceAttr("redshift_user.user_with_defaults", "valid_until", "infinity"),
resource.TestCheckResourceAttr("redshift_user.user_with_defaults", "syslog_access", "RESTRICTED"),
resource.TestCheckResourceAttr("redshift_user.user_with_defaults", "session_timeout", "0"),

testAccCheckRedshiftUserExists("user_create_database"),
resource.TestCheckResourceAttr("redshift_user.user_with_create_database", "name", "user_create_database"),
Expand All @@ -51,6 +52,10 @@ func TestAccRedshiftUser_Basic(t *testing.T) {
testAccCheckRedshiftUserExists("user_superuser"),
resource.TestCheckResourceAttr("redshift_user.user_superuser", "name", "user_superuser"),
resource.TestCheckResourceAttr("redshift_user.user_superuser", "superuser", "true"),

testAccCheckRedshiftUserExists("user_timeout"),
resource.TestCheckResourceAttr("redshift_user.user_timeout", "name", "user_timeout"),
resource.TestCheckResourceAttr("redshift_user.user_timeout", "session_timeout", "60"),
),
},
},
Expand Down Expand Up @@ -375,6 +380,12 @@ resource "redshift_user" "user_superuser" {
superuser = true
password = "FooBarBaz123"
}

resource "redshift_user" "user_timeout" {
name = "user_timeout"
password = "FooBarBaz123"
session_timeout = 60
}
`

func TestPermanentUsername(t *testing.T) {
Expand Down