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

feat: add on_account to session and object params #1685

Merged
merged 5 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions docs/data-sources/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ data "snowflake_parameters" "p2" {
data "snowflake_parameters" "p3" {
parameter_type = "SESSION"
pattern = "ROWS_PER_RESULTSET"
user = "TEST_USER"
}
```

Expand All @@ -46,6 +47,7 @@ data "snowflake_parameters" "p3" {
- `object_type` (String) If parameter_type is set to "OBJECT" then object_type is the type of object to display object parameters for. Valid values are any object supported by the IN clause of the [SHOW PARAMETERS](https://docs.snowflake.com/en/sql-reference/sql/show-parameters.html#parameters) statement, including: WAREHOUSE | DATABASE | SCHEMA | TASK | TABLE
- `parameter_type` (String) The type of parameter to filter by. Valid values are: "ACCOUNT", "SESSION", "OBJECT".
- `pattern` (String) Allows limiting the list of parameters by name using LIKE clause. Refer to [Limiting the List of Parameters by Name](https://docs.snowflake.com/en/sql-reference/parameters.html#limiting-the-list-of-parameters-by-name)
- `user` (String) If parameter_type is set to "SESSION" then user is the name of the user to display session parameters for.

### Read-Only

Expand Down
6 changes: 4 additions & 2 deletions docs/resources/object_parameter.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ resource "snowflake_object_parameter" "o3" {

// Setting object parameter at account level
resource "snowflake_object_parameter" "o4" {
key = "DATA_RETENTION_TIME_IN_DAYS"
value = "89"
key = "DATA_RETENTION_TIME_IN_DAYS"
value = "89"
on_account = true
}
```

Expand All @@ -81,6 +82,7 @@ resource "snowflake_object_parameter" "o4" {

- `object_identifier` (Block List) Specifies the object identifier for the object parameter. If no value is provided, then the resource will default to setting the object parameter at account level. (see [below for nested schema](#nestedblock--object_identifier))
- `object_type` (String) Type of object to which the parameter applies. Valid values are those in [object types](https://docs.snowflake.com/en/sql-reference/parameters.html#object-types). If no value is provided, then the resource will default to setting the object parameter at account level.
- `on_account` (Boolean) If true, the object parameter will be set on the account level.

### Read-Only

Expand Down
12 changes: 12 additions & 0 deletions docs/resources/session_parameter.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ description: |-
resource "snowflake_session_parameter" "s" {
key = "AUTOCOMMIT"
value = "false"
user = "TEST_USER"
}

resource "snowflake_session_parameter" "s2" {
key = "BINARY_OUTPUT_FORMAT"
value = "BASE64"
on_account = true
}
```

Expand All @@ -27,6 +34,11 @@ resource "snowflake_session_parameter" "s" {
- `key` (String) Name of session parameter. Valid values are those in [session parameters](https://docs.snowflake.com/en/sql-reference/parameters.html#session-parameters).
- `value` (String) Value of session parameter, as a string. Constraints are the same as those for the parameters in Snowflake documentation.

### Optional

- `on_account` (Boolean) If true, the session parameter will be set on the account level.
- `user` (String) The user to set the session parameter for. Required if on_account is false

### Read-Only

- `id` (String) The ID of this resource.
Expand Down
1 change: 1 addition & 0 deletions examples/data-sources/snowflake_parameters/data-source.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ data "snowflake_parameters" "p2" {
data "snowflake_parameters" "p3" {
parameter_type = "SESSION"
pattern = "ROWS_PER_RESULTSET"
user = "TEST_USER"
}
5 changes: 3 additions & 2 deletions examples/resources/snowflake_object_parameter/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ resource "snowflake_object_parameter" "o3" {

// Setting object parameter at account level
resource "snowflake_object_parameter" "o4" {
key = "DATA_RETENTION_TIME_IN_DAYS"
value = "89"
key = "DATA_RETENTION_TIME_IN_DAYS"
value = "89"
on_account = true
}
7 changes: 7 additions & 0 deletions examples/resources/snowflake_session_parameter/resource.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
resource "snowflake_session_parameter" "s" {
key = "AUTOCOMMIT"
value = "false"
user = "TEST_USER"
}

resource "snowflake_session_parameter" "s2" {
key = "BINARY_OUTPUT_FORMAT"
value = "BASE64"
on_account = true
}
47 changes: 20 additions & 27 deletions pkg/datasources/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package datasources
import (
"database/sql"
"errors"
"fmt"
"log"
"strings"

Expand All @@ -15,7 +16,7 @@ var parametersSchema = map[string]*schema.Schema{
"parameter_type": {
Type: schema.TypeString,
Optional: true,
Default: "SESSION",
Default: "ACCOUNT",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this backward compatible?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the old behavior "SESSION" was actually the same as "ACCOUNT", hence setting it as "ACCOUNT" is the most sensible. This is generally what people want to do anyways

Description: "The type of parameter to filter by. Valid values are: \"ACCOUNT\", \"SESSION\", \"OBJECT\".",
ValidateFunc: validation.StringInSlice([]string{"ACCOUNT", "SESSION", "OBJECT"}, true),
},
Expand All @@ -24,6 +25,11 @@ var parametersSchema = map[string]*schema.Schema{
Optional: true,
Description: "Allows limiting the list of parameters by name using LIKE clause. Refer to [Limiting the List of Parameters by Name](https://docs.snowflake.com/en/sql-reference/parameters.html#limiting-the-list-of-parameters-by-name)",
},
"user": {
Type: schema.TypeString,
Optional: true,
Description: "If parameter_type is set to \"SESSION\" then user is the name of the user to display session parameters for.",
},
"object_type": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -90,37 +96,24 @@ func ReadParameters(d *schema.ResourceData, meta interface{}) error {
if ok {
pattern = p.(string)
}
var parameters []snowflake.Parameter
var err error
parameterType := snowflake.ParameterType(strings.ToUpper(d.Get("parameter_type").(string)))
if parameterType == snowflake.ParameterTypeObject {
switch parameterType {
case snowflake.ParameterTypeAccount:
parameters, err = snowflake.ListAccountParameters(db, pattern)
case snowflake.ParameterTypeSession:
user := d.Get("user").(string)
if user == "" {
return fmt.Errorf("user is required when parameter_type is set to SESSION")
}
parameters, err = snowflake.ListSessionParameters(db, pattern, user)
case snowflake.ParameterTypeObject:
oType := d.Get("object_type").(string)
objectType := snowflake.ObjectType(oType)
objectName := d.Get("object_name").(string)
parameters, err := snowflake.ListObjectParameters(db, objectType, objectName, pattern)
if errors.Is(err, sql.ErrNoRows) {
log.Printf("[DEBUG] parameters not found")
d.SetId("")
return nil
} else if err != nil {
log.Printf("[DEBUG] error occurred during read: %v", err.Error())
return err
}
d.SetId("parameters")
params := []map[string]interface{}{}
for _, param := range parameters {
paramMap := map[string]interface{}{}

paramMap["key"] = param.Key.String
paramMap["value"] = param.Value.String
paramMap["default"] = param.Default.String
paramMap["level"] = param.Level.String
paramMap["description"] = param.Description.String
paramMap["type"] = param.PType.String

params = append(params, paramMap)
}
return d.Set("parameters", params)
parameters, err = snowflake.ListObjectParameters(db, objectType, objectName, pattern)
}
parameters, err := snowflake.ListParameters(db, parameterType, pattern)
if errors.Is(err, sql.ErrNoRows) {
log.Printf("[DEBUG] parameters not found")
d.SetId("")
Expand Down
80 changes: 76 additions & 4 deletions pkg/datasources/parameters_acceptance_test.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,100 @@
package datasources_test

import (
"fmt"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAcc_Parameters(t *testing.T) {
func TestAcc_ParametersOnAccount(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: parameters(),
Config: parametersConfigOnAccount(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.snowflake_parameters.p", "pattern", "AUTOCOMMIT"),
resource.TestCheckResourceAttr("data.snowflake_parameters.p", "parameters.#", "1"),
resource.TestCheckResourceAttr("data.snowflake_parameters.p", "parameters.0.key", "AUTOCOMMIT"),
resource.TestCheckResourceAttrSet("data.snowflake_parameters.p", "parameters.0.value"),
),
},
},
})
}

func TestAcc_ParametersOnSession(t *testing.T) {
userName := "TEST_USER_" + strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: parametersConfigOnSession(userName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.snowflake_parameters.p", "parameters.#"),
resource.TestCheckResourceAttrSet("data.snowflake_parameters.p", "parameters.0.key"),
resource.TestCheckResourceAttrSet("data.snowflake_parameters.p", "parameters.0.value"),
resource.TestCheckResourceAttr("data.snowflake_parameters.p", "user", userName),
),
},
},
})
}

func parameters() string {
return `data "snowflake_parameters" "p" {}`
func TestAcc_ParametersOnObject(t *testing.T) {
dbName := "TEST_DB_" + strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha))
resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: parametersConfigOnObject(dbName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.snowflake_parameters.p", "parameters.#"),
resource.TestCheckResourceAttrSet("data.snowflake_parameters.p", "parameters.0.key"),
resource.TestCheckResourceAttrSet("data.snowflake_parameters.p", "parameters.0.value"),
resource.TestCheckResourceAttr("data.snowflake_parameters.p", "object_type", "DATABASE"),
resource.TestCheckResourceAttr("data.snowflake_parameters.p", "object_name", dbName),
),
},
},
})
}

func parametersConfigOnAccount() string {
return `data "snowflake_parameters" "p" {
parameter_type = "ACCOUNT"
pattern = "AUTOCOMMIT"
}`
}

func parametersConfigOnSession(user string) string {
s := `
resource "snowflake_user" "u" {
name = "%s"
}

data "snowflake_parameters" "p" {
parameter_type = "SESSION"
user = snowflake_user.u.name
}`
return fmt.Sprintf(s, user)
}

func parametersConfigOnObject(name string) string {
stmt := `
resource "snowflake_database" "d" {
name = "%s"
}
data "snowflake_parameters" "p" {
parameter_type = "OBJECT"
object_type = "DATABASE"
object_name = snowflake_database.d.name
}`
return fmt.Sprintf(stmt, name)
}
4 changes: 2 additions & 2 deletions pkg/resources/account_parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func CreateAccountParameter(d *schema.ResourceData, meta interface{}) error {
value = fmt.Sprintf("'%s'", snowflake.EscapeString(value))
}

builder := snowflake.NewParameter(key, value, snowflake.ParameterTypeAccount, db)
builder := snowflake.NewAccountParameter(key, value, db)
err := builder.SetParameter()
if err != nil {
return fmt.Errorf("error creating account parameter err = %w", err)
Expand Down Expand Up @@ -111,7 +111,7 @@ func DeleteAccountParameter(d *schema.ResourceData, meta interface{}) error {
if reflect.TypeOf(parameterDefault.DefaultValue) == typeString {
value = fmt.Sprintf("'%s'", value)
}
builder := snowflake.NewParameter(key, value, snowflake.ParameterTypeAccount, db)
builder := snowflake.NewAccountParameter(key, value, db)
err := builder.SetParameter()
if err != nil {
return fmt.Errorf("error creating account parameter err = %w", err)
Expand Down
39 changes: 26 additions & 13 deletions pkg/resources/object_parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ var objectParameterSchema = map[string]*schema.Schema{
Required: true,
Description: "Value of object parameter, as a string. Constraints are the same as those for the parameters in Snowflake documentation.",
},
"on_account": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "If true, the object parameter will be set on the account level.",
},
"object_type": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -99,7 +105,12 @@ func CreateObjectParameter(d *schema.ResourceData, meta interface{}) error {
value = fmt.Sprintf("'%s'", snowflake.EscapeString(value))
}

builder := snowflake.NewParameter(key, value, snowflake.ParameterTypeObject, db)
builder := snowflake.NewObjectParameter(key, value, db)

onAccount := d.Get("on_account").(bool)
if onAccount {
builder.SetOnAccount(onAccount)
}

var fullyQualifierObjectIdentifier string
if v, ok := d.GetOk("object_identifier"); ok {
Expand All @@ -121,7 +132,7 @@ func CreateObjectParameter(d *schema.ResourceData, meta interface{}) error {
if err != nil {
return fmt.Errorf("error creating object parameter err = %w", err)
}
id := fmt.Sprintf("%v❄️%v❄️%v", key, objectType, fullyQualifierObjectIdentifier)
id := fmt.Sprintf("%v|%v|%v", key, objectType, fullyQualifierObjectIdentifier)
d.SetId(id)
var p *snowflake.Parameter
if fullyQualifierObjectIdentifier != "" {
Expand All @@ -143,9 +154,12 @@ func CreateObjectParameter(d *schema.ResourceData, meta interface{}) error {
func ReadObjectParameter(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)
id := d.Id()
parts := strings.Split(id, "❄️")
parts := strings.Split(id, "|")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth extracting "|" into a global variable to avoid magic values.

if len(parts) != 3 {
parts = strings.Split(id, "❄️") // for backwards compatibility
}
if len(parts) != 3 {
return fmt.Errorf("unexpected format of ID (%v), expected key❄️object_type❄️object_identifier", id)
return fmt.Errorf("unexpected format of ID (%v), expected key|object_type|object_identifier", id)
}
key := parts[0]
var p *snowflake.Parameter
Expand Down Expand Up @@ -185,14 +199,20 @@ func DeleteObjectParameter(d *schema.ResourceData, meta interface{}) error {
if reflect.TypeOf(parameterDefault.DefaultValue) == typeString {
value = fmt.Sprintf("'%s'", value)
}
builder := snowflake.NewParameter(key, value, snowflake.ParameterTypeObject, db)
builder := snowflake.NewObjectParameter(key, value, db)

onAccount := d.Get("on_account").(bool)
if onAccount {
builder.SetOnAccount(onAccount)
}

var fullyQualifierObjectIdentifier string
if v, ok := d.GetOk("object_identifier"); ok {
objectDatabase, objectSchema, objectName := expandObjectIdentifier(v.([]interface{}))
fullyQualifierObjectIdentifier = snowflakeValidation.FormatFullyQualifiedObjectID(objectDatabase, objectSchema, objectName)
builder.WithObjectIdentifier(fullyQualifierObjectIdentifier)
}

var objectType snowflake.ObjectType
if v, ok := d.GetOk("object_type"); ok {
objectType = snowflake.ObjectType(v.(string))
Expand All @@ -201,18 +221,11 @@ func DeleteObjectParameter(d *schema.ResourceData, meta interface{}) error {
}
builder.WithObjectType(objectType)
}

err := builder.SetParameter()
if err != nil {
return fmt.Errorf("error deleting object parameter err = %w", err)
}
if fullyQualifierObjectIdentifier != "" {
_, err = snowflake.ShowObjectParameter(db, key, objectType, fullyQualifierObjectIdentifier)
} else {
_, err = snowflake.ShowAccountParameter(db, key)
}
if err != nil {
return fmt.Errorf("error reading object parameter err = %w", err)
}

d.SetId("")
return nil
Expand Down
Loading