From 4e2ba31ef04f21974be9873e264405fb00fc27f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Thu, 13 Jun 2024 15:13:32 +0200 Subject: [PATCH] changes after review --- MIGRATION_GUIDE.md | 35 ++- docs/resources/database_old.md | 2 +- .../snowflake_database_old/import.sh | 2 +- pkg/acceptance/asserts.go | 2 +- pkg/acceptance/asserts_test.go | 25 +- pkg/acceptance/check_destroy.go | 6 +- pkg/acceptance/helpers/parameter_client.go | 18 +- pkg/acceptance/snowflakechecks/database.go | 10 +- pkg/datasources/databases_acceptance_test.go | 2 +- pkg/resources/custom_diffs.go | 53 ++-- pkg/resources/custom_diffs_test.go | 4 +- pkg/resources/database.go | 8 +- pkg/resources/database_acceptance_test.go | 14 +- pkg/resources/database_commons.go | 62 +++-- pkg/resources/database_state_upgraders.go | 10 - pkg/resources/helpers.go | 5 +- pkg/resources/helpers_test.go | 7 + pkg/resources/secondary_database.go | 8 +- .../secondary_database_acceptance_test.go | 235 +++++++++--------- pkg/resources/shared_database.go | 8 +- 20 files changed, 285 insertions(+), 231 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index a69d0f6c31..0326d84de8 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -66,6 +66,37 @@ As part of the [preparation for v1](https://github.com/Snowflake-Labs/terraform- - Shared database - can be used as `snowflake_shared_database` (used to create databases from externally defined shares) - Secondary database - can be used as `snowflake_secondary_database` (used to create replicas of databases from external sources) +All the field changes in comparison to the previous database resource are: +- `is_transient` + - in `snowflake_shared_database` + - removed: the field is removed from `snowflake_shared_database` as it doesn't have any effect on shared databases. +- `from_database` - database cloning was entirely removed and is not possible by any of the new database resources. +- `from_share` - the parameter was moved to the dedicated resource for databases created from shares `snowflake_shared_database`. Right now, it's a text field instead of a map. Additionally, instead of legacy account identifier format we're expecting the new one that with share looks like this: `..`. For more information on account identifiers, visit the [official documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier). +- p, +- `from_replication` - the parameter was moved to the dedicated resource for databases created from primary databases `snowflake_secondary_database` +- `replication_configuration` - renamed: was renamed to `configuration` and is only available in the `snowflake_database`. Its internal schema changed that instead of list of accounts, we expect a list of nested objects with accounts for which replication (and optionally failover) should be enabled. More information about converting between both versions [here](#resource-renamed-snowflake_database---snowflake_database_old). Additionally, instead of legacy account identifier format we're expecting the new one that looks like this: `.`. For more information on account identifiers, visit the [official documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier). +- `data_retention_time_in_days` + - in `snowflake_shared_database` + - removed: the field is removed from `snowflake_shared_database` as it doesn't have any effect on shared databases. + - in `snowflake_database` and `snowflake_secondary_database` + - adjusted: now, it uses different approach that won't set it to -1 as a default value, but rather fills the field with the current value from Snowflake (this still can change). +- added: The following set of [parameters](https://docs.snowflake.com/en/sql-reference/parameters) was added to every database type: + - `max_data_extension_time_in_days` + - `external_volume` + - `catalog` + - `replace_invalid_characters` + - `default_ddl_collation` + - `storage_serialization_policy` + - `log_level` + - `trace_level` + - `suspend_task_after_num_failures` + - `task_auto_retry_attempts` + - `user_task_managed_initial_warehouse_size` + - `user_task_timeout_ms` + - `user_task_minimum_trigger_interval_in_seconds` + - `quoted_identifiers_ignore_case` + - `enable_console_output` + The split was done (and will be done for several objects during the refactor) to simplify the resource on maintainability and usage level. Its purpose was also to divide the resources by their specific purpose rather than cramping every use case of an object into one resource. @@ -125,7 +156,9 @@ The only difference would be that instead of writing/generating new configuratio - `pattern` was replaced by `like` field. - Additional filtering options added (`limit`). - Added missing fields returned by SHOW DATABASES. -- Added outputs from DESC DATABASE and SHOW PARAMETERS IN DATABASE (they can be turned off by declaring `with_describe = false` and `with_parameters = false`, **they're turned on by default**). +- Added outputs from **DESC DATABASE** and **SHOW PARAMETERS IN DATABASE** (they can be turned off by declaring `with_describe = false` and `with_parameters = false`, **they're turned on by default**). +The additional parameters call **DESC DATABASE** (with `with_describe` turned on) and **SHOW PARAMETERS IN DATABASE** (with `with_parameters` turned on) **per database** returned by **SHOW DATABASES**. +It's important to limit the records and calls to Snowflake to the minimum. That's why we recommend assessing which information you need from the data source and then providing strong filters and turning off additional fields for better plan performance. ## v0.89.0 ➞ v0.90.0 ### snowflake_table resource changes diff --git a/docs/resources/database_old.md b/docs/resources/database_old.md index 89a4d437f5..e6fdecabe8 100644 --- a/docs/resources/database_old.md +++ b/docs/resources/database_old.md @@ -81,5 +81,5 @@ Optional: Import is supported using the following syntax: ```shell -terraform import snowflake_database_old.example name +terraform import snowflake_database_old.example 'database_name' ``` diff --git a/examples/resources/snowflake_database_old/import.sh b/examples/resources/snowflake_database_old/import.sh index 65c34ff086..3ea61a2c21 100644 --- a/examples/resources/snowflake_database_old/import.sh +++ b/examples/resources/snowflake_database_old/import.sh @@ -1 +1 @@ -terraform import snowflake_database_old.example name +terraform import snowflake_database_old.example 'database_name' diff --git a/pkg/acceptance/asserts.go b/pkg/acceptance/asserts.go index a6db735068..4ce547dfa9 100644 --- a/pkg/acceptance/asserts.go +++ b/pkg/acceptance/asserts.go @@ -15,7 +15,7 @@ func IsGreaterOrEqualTo(greaterOrEqualValue int) resource.CheckResourceAttrWithF } if intValue < greaterOrEqualValue { - return fmt.Errorf("expected value %d greater or equal to %d", intValue, greaterOrEqualValue) + return fmt.Errorf("expected value %d to be greater or equal to %d", intValue, greaterOrEqualValue) } return nil diff --git a/pkg/acceptance/asserts_test.go b/pkg/acceptance/asserts_test.go index f916f91eda..6d7e488d7f 100644 --- a/pkg/acceptance/asserts_test.go +++ b/pkg/acceptance/asserts_test.go @@ -17,7 +17,25 @@ func TestIsGreaterOrEqualTo(t *testing.T) { Name: "validation: smaller than expected", GreaterOrEqualTo: 20, Actual: "10", - Error: "expected value 10 greater or equal to 20", + Error: "expected value 10 to be greater or equal to 20", + }, + { + Name: "validation: zero actual value", + GreaterOrEqualTo: 20, + Actual: "0", + Error: "expected value 0 to be greater or equal to 20", + }, + { + Name: "validation: zero greater value", + GreaterOrEqualTo: 0, + Actual: "-10", + Error: "expected value -10 to be greater or equal to 0", + }, + { + Name: "validation: negative value", + GreaterOrEqualTo: -20, + Actual: "-30", + Error: "expected value -30 to be greater or equal to -20", }, { Name: "validation: not int value", @@ -35,6 +53,11 @@ func TestIsGreaterOrEqualTo(t *testing.T) { GreaterOrEqualTo: 20, Actual: "30", }, + { + Name: "validation: greater value with expected negative value", + GreaterOrEqualTo: -20, + Actual: "30", + }, } for _, testCase := range testCases { diff --git a/pkg/acceptance/check_destroy.go b/pkg/acceptance/check_destroy.go index b598db323f..68b9054c78 100644 --- a/pkg/acceptance/check_destroy.go +++ b/pkg/acceptance/check_destroy.go @@ -70,6 +70,9 @@ var showByIdFunctions = map[resources.Resource]showByIdFunc{ resources.ApiIntegration: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.ApiIntegrations.ShowByID) }, + resources.Database: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { + return runShowById(ctx, id, client.Databases.ShowByID) + }, resources.DatabaseOld: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Databases.ShowByID) }, @@ -154,9 +157,6 @@ var showByIdFunctions = map[resources.Resource]showByIdFunc{ resources.Stage: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Stages.ShowByID) }, - resources.Database: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { - return runShowById(ctx, id, client.Databases.ShowByID) - }, resources.StorageIntegration: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.StorageIntegrations.ShowByID) }, diff --git a/pkg/acceptance/helpers/parameter_client.go b/pkg/acceptance/helpers/parameter_client.go index abed54de35..54435b4c63 100644 --- a/pkg/acceptance/helpers/parameter_client.go +++ b/pkg/acceptance/helpers/parameter_client.go @@ -3,9 +3,10 @@ package helpers import ( "context" "fmt" - "slices" "testing" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/collections" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/stretchr/testify/require" ) @@ -46,13 +47,6 @@ func (c *ParameterClient) ShowDatabaseParameters(t *testing.T, id sdk.AccountObj return params } -func (c *ParameterClient) GetAccountParameter(t *testing.T, parameter sdk.AccountParameter) *sdk.Parameter { - t.Helper() - param, err := c.client().ShowAccountParameter(context.Background(), parameter) - require.NoError(t, err) - return param -} - func (c *ParameterClient) UpdateAccountParameterTemporarily(t *testing.T, parameter sdk.AccountParameter, newValue string) func() { t.Helper() ctx := context.Background() @@ -95,9 +89,7 @@ func (c *ParameterClient) UnsetAccountParameter(t *testing.T, parameter sdk.Acco func FindParameter(t *testing.T, parameters []*sdk.Parameter, parameter sdk.AccountParameter) *sdk.Parameter { t.Helper() - idx := slices.IndexFunc(parameters, func(p *sdk.Parameter) bool { - return p.Key == string(parameter) - }) - require.NotEqual(t, -1, idx, fmt.Sprintf("parameter %s not found", string(parameter))) - return parameters[idx] + param, err := collections.FindOne(parameters, func(p *sdk.Parameter) bool { return p.Key == string(parameter) }) + require.NoError(t, err) + return *param } diff --git a/pkg/acceptance/snowflakechecks/database.go b/pkg/acceptance/snowflakechecks/database.go index 4c318136ff..f3630aa2e1 100644 --- a/pkg/acceptance/snowflakechecks/database.go +++ b/pkg/acceptance/snowflakechecks/database.go @@ -12,16 +12,16 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" ) -func CheckDatabaseDataRetentionTimeInDays(t *testing.T, databaseId sdk.AccountObjectIdentifier, level string, value string) resource.TestCheckFunc { +func CheckDatabaseDataRetentionTimeInDays(t *testing.T, databaseId sdk.AccountObjectIdentifier, expectedLevel sdk.ParameterType, expectedValue string) resource.TestCheckFunc { t.Helper() return func(state *terraform.State) error { param := helpers.FindParameter(t, acc.TestClient().Parameter.ShowDatabaseParameters(t, databaseId), sdk.AccountParameterDataRetentionTimeInDays) var errs []error - if param.Level != sdk.ParameterType(level) { - errs = append(errs, fmt.Errorf("expected parameter level %s, got %s", sdk.ParameterType(level), param.Level)) + if param.Level != expectedLevel { + errs = append(errs, fmt.Errorf("expected parameter level %s, got %s", expectedLevel, param.Level)) } - if param.Value != value { - errs = append(errs, fmt.Errorf("expected parameter value %s, got %s", sdk.ParameterType(level), param.Level)) + if param.Value != expectedValue { + errs = append(errs, fmt.Errorf("expected parameter value %s, got %s", expectedLevel, param.Level)) } return errors.Join(errs...) } diff --git a/pkg/datasources/databases_acceptance_test.go b/pkg/datasources/databases_acceptance_test.go index 149fc07cbe..2da4fa3d31 100644 --- a/pkg/datasources/databases_acceptance_test.go +++ b/pkg/datasources/databases_acceptance_test.go @@ -93,7 +93,7 @@ func TestAcc_Databases_Complete(t *testing.T) { } func TestAcc_Databases_DifferentFiltering(t *testing.T) { - prefix := acc.TestClient().Ids.Alpha() + prefix := random.String() idOne := acc.TestClient().Ids.RandomAccountObjectIdentifierWithPrefix(prefix) idTwo := acc.TestClient().Ids.RandomAccountObjectIdentifierWithPrefix(prefix) idThree := acc.TestClient().Ids.RandomAccountObjectIdentifier() diff --git a/pkg/resources/custom_diffs.go b/pkg/resources/custom_diffs.go index 86c463672a..d050a253f8 100644 --- a/pkg/resources/custom_diffs.go +++ b/pkg/resources/custom_diffs.go @@ -5,6 +5,8 @@ import ( "log" "strconv" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/collections" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" @@ -13,58 +15,43 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func AccountObjectStringValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { - return ValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return value.(string) }) +func StringParameterValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { + return ParameterValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return value.(string) }) } -func AccountObjectIntValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { - return ValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return strconv.Itoa(value.(int)) }) +func IntParameterValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { + return ParameterValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return strconv.Itoa(value.(int)) }) } -func AccountObjectBoolValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { - return ValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return strconv.FormatBool(value.(bool)) }) +func BoolParameterValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { + return ParameterValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return strconv.FormatBool(value.(bool)) }) } -func ValueComputedIf(key string, parameters []*sdk.Parameter, objectParameterLevel sdk.ParameterType, accountParameter sdk.AccountParameter, valueToString func(v any) string) schema.CustomizeDiffFunc { - var parameterValue *string - var parameterLevel *sdk.ParameterType - - for _, parameter := range parameters { - if parameter.Key == string(accountParameter) { - parameterLevel = ¶meter.Level - parameterValue = ¶meter.Value - break +func ParameterValueComputedIf(key string, parameters []*sdk.Parameter, objectParameterLevel sdk.ParameterType, accountParameter sdk.AccountParameter, valueToString func(v any) string) schema.CustomizeDiffFunc { + return func(ctx context.Context, d *schema.ResourceDiff, meta any) error { + foundParameter, err := collections.FindOne(parameters, func(parameter *sdk.Parameter) bool { return parameter.Key == string(accountParameter) }) + if err != nil { + log.Printf("[WARN] failed to find account parameter: %s", accountParameter) + return nil } - } + parameter := *foundParameter - condition := func(ctx context.Context, d *schema.ResourceDiff, meta any) bool { configValue, ok := d.GetRawConfig().AsValueMap()[key] - if parameterLevel == nil || parameterValue == nil { - log.Printf("[ERROR] ValueComputedIf, parameter %s not found", accountParameter) - return false - } - // For cases where currently set value (in the config) is equal to the parameter, but not set on the right level. // The parameter is set somewhere higher in the hierarchy, and we need to "forcefully" set the value to // perform the actual set on Snowflake (and set the parameter on the correct level). - if *parameterLevel != objectParameterLevel && !configValue.IsNull() && *parameterValue == valueToString(d.Get(key)) { - return true + if ok && !configValue.IsNull() && parameter.Level != objectParameterLevel && parameter.Value == valueToString(d.Get(key)) { + return d.SetNewComputed(key) } // For all other cases, if a parameter is set in the configuration, we can ignore parts needed for Computed fields. if ok && !configValue.IsNull() { - return false + return nil } - // If the configuration is not set, perform SetNewComputed for cases like: - // 1. Check if the parameter value differs from the one saved in state (if they differ, we'll update the computed value). - // 2. Check if the parameter level is set on the same level for the given object (if they're the same, we'll trigger the unset as it has been updated in Snowflake). - return *parameterValue != valueToString(d.Get(key)) || *parameterLevel == objectParameterLevel - } - - return func(ctx context.Context, d *schema.ResourceDiff, meta any) error { - if condition(ctx, d, meta) { + // Check if the parameter is set on the object level (if so, it means that it was set externally, and we have to unset it). + if parameter.Level == objectParameterLevel { return d.SetNewComputed(key) } diff --git a/pkg/resources/custom_diffs_test.go b/pkg/resources/custom_diffs_test.go index ff3172d0ed..17bcc3ae90 100644 --- a/pkg/resources/custom_diffs_test.go +++ b/pkg/resources/custom_diffs_test.go @@ -16,9 +16,9 @@ import ( "github.com/stretchr/testify/require" ) -func TestValueComputedIf(t *testing.T) { +func TestParameterValueComputedIf(t *testing.T) { createProviderConfig := func(parameterLevel sdk.ParameterType, parameterValue sdk.LogLevel) *schema.Provider { - customDiff := resources.ValueComputedIf( + customDiff := resources.ParameterValueComputedIf( "value", []*sdk.Parameter{ { diff --git a/pkg/resources/database.go b/pkg/resources/database.go index bb7ce6a682..921c407a66 100644 --- a/pkg/resources/database.go +++ b/pkg/resources/database.go @@ -121,9 +121,13 @@ func CreateDatabase(ctx context.Context, d *schema.ResourceData, meta any) diag. userTaskTimeoutMs, userTaskMinimumTriggerIntervalInSeconds, quotedIdentifiersIgnoreCase, - enableConsoleOutput := GetAllDatabaseParameters(d) + enableConsoleOutput, + err := GetAllDatabaseParameters(d) + if err != nil { + return diag.FromErr(err) + } - err := client.Databases.Create(ctx, id, &sdk.CreateDatabaseOptions{ + err = client.Databases.Create(ctx, id, &sdk.CreateDatabaseOptions{ Transient: GetPropertyAsPointer[bool](d, "is_transient"), DataRetentionTimeInDays: dataRetentionTimeInDays, MaxDataExtensionTimeInDays: maxDataExtensionTimeInDays, diff --git a/pkg/resources/database_acceptance_test.go b/pkg/resources/database_acceptance_test.go index 98444e22da..d3ca14d703 100644 --- a/pkg/resources/database_acceptance_test.go +++ b/pkg/resources/database_acceptance_test.go @@ -525,7 +525,7 @@ func TestAcc_Database_HierarchicalValues(t *testing.T) { Steps: []resource.TestStep{ { PreConfig: func() { - *paramDefault = acc.TestClient().Parameter.GetAccountParameter(t, sdk.AccountParameterMaxDataExtensionTimeInDays).Default + *paramDefault = acc.TestClient().Parameter.ShowAccountParameter(t, sdk.AccountParameterMaxDataExtensionTimeInDays).Default }, ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Database/basic"), ConfigVariables: configVariables(id, comment), @@ -761,7 +761,7 @@ func TestAcc_Database_IntParameter(t *testing.T) { }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_database.test", "data_retention_time_in_days", "25"), - snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, "DATABASE", "25"), + snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, sdk.ParameterTypeDatabase, "25"), ), }, // remove the param from config @@ -806,7 +806,7 @@ func TestAcc_Database_IntParameter(t *testing.T) { }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_database.test", "data_retention_time_in_days", "1"), - snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, "DATABASE", "1"), + snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, sdk.ParameterTypeDatabase, "1"), ), }, // remove the param from config @@ -849,7 +849,7 @@ func TestAcc_Database_IntParameter(t *testing.T) { }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_database.test", "data_retention_time_in_days", "50"), - snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, "ACCOUNT", "50"), + snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, sdk.ParameterTypeAccount, "50"), ), }, // import when param not in config (set on account) @@ -861,7 +861,7 @@ func TestAcc_Database_IntParameter(t *testing.T) { importchecks.TestCheckResourceAttrInstanceState(id.Name(), "data_retention_time_in_days", "50"), ), Check: resource.ComposeTestCheckFunc( - snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, "ACCOUNT", "50"), + snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, sdk.ParameterTypeAccount, "50"), ), }, // change param value on database @@ -880,7 +880,7 @@ func TestAcc_Database_IntParameter(t *testing.T) { }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_database.test", "data_retention_time_in_days", "50"), - snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, "ACCOUNT", "50"), + snowflakechecks.CheckDatabaseDataRetentionTimeInDays(t, id, sdk.ParameterTypeAccount, "50"), ), }, // unset param on account @@ -907,7 +907,7 @@ func TestAcc_Database_IntParameter(t *testing.T) { }) } -func TestAcc_Database_BasicUpgrade(t *testing.T) { +func TestAcc_Database_UpgradeWithTheSameFieldsAsInTheOldOne(t *testing.T) { id := acc.TestClient().Ids.RandomAccountObjectIdentifier() comment := random.Comment() dataRetentionTimeInDays := new(string) diff --git a/pkg/resources/database_commons.go b/pkg/resources/database_commons.go index 8a19a15bc6..0f3fb84f1a 100644 --- a/pkg/resources/database_commons.go +++ b/pkg/resources/database_commons.go @@ -40,26 +40,23 @@ var ( return err } - if err != nil { - return err - } return customdiff.All( - AccountObjectIntValueComputedIf("data_retention_time_in_days", params, sdk.ParameterTypeDatabase, sdk.AccountParameterDataRetentionTimeInDays), - AccountObjectIntValueComputedIf("max_data_extension_time_in_days", params, sdk.ParameterTypeDatabase, sdk.AccountParameterMaxDataExtensionTimeInDays), - AccountObjectStringValueComputedIf("external_volume", params, sdk.ParameterTypeDatabase, sdk.AccountParameterExternalVolume), - AccountObjectStringValueComputedIf("catalog", params, sdk.ParameterTypeDatabase, sdk.AccountParameterCatalog), - AccountObjectBoolValueComputedIf("replace_invalid_characters", params, sdk.ParameterTypeDatabase, sdk.AccountParameterReplaceInvalidCharacters), - AccountObjectStringValueComputedIf("default_ddl_collation", params, sdk.ParameterTypeDatabase, sdk.AccountParameterDefaultDDLCollation), - AccountObjectStringValueComputedIf("storage_serialization_policy", params, sdk.ParameterTypeDatabase, sdk.AccountParameterStorageSerializationPolicy), - AccountObjectStringValueComputedIf("log_level", params, sdk.ParameterTypeDatabase, sdk.AccountParameterLogLevel), - AccountObjectStringValueComputedIf("trace_level", params, sdk.ParameterTypeDatabase, sdk.AccountParameterTraceLevel), - AccountObjectIntValueComputedIf("suspend_task_after_num_failures", params, sdk.ParameterTypeDatabase, sdk.AccountParameterSuspendTaskAfterNumFailures), - AccountObjectIntValueComputedIf("task_auto_retry_attempts", params, sdk.ParameterTypeDatabase, sdk.AccountParameterTaskAutoRetryAttempts), - AccountObjectStringValueComputedIf("user_task_managed_initial_warehouse_size", params, sdk.ParameterTypeDatabase, sdk.AccountParameterUserTaskManagedInitialWarehouseSize), - AccountObjectIntValueComputedIf("user_task_timeout_ms", params, sdk.ParameterTypeDatabase, sdk.AccountParameterUserTaskTimeoutMs), - AccountObjectIntValueComputedIf("user_task_minimum_trigger_interval_in_seconds", params, sdk.ParameterTypeDatabase, sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds), - AccountObjectBoolValueComputedIf("quoted_identifiers_ignore_case", params, sdk.ParameterTypeDatabase, sdk.AccountParameterQuotedIdentifiersIgnoreCase), - AccountObjectBoolValueComputedIf("enable_console_output", params, sdk.ParameterTypeDatabase, sdk.AccountParameterEnableConsoleOutput), + IntParameterValueComputedIf("data_retention_time_in_days", params, sdk.ParameterTypeDatabase, sdk.AccountParameterDataRetentionTimeInDays), + IntParameterValueComputedIf("max_data_extension_time_in_days", params, sdk.ParameterTypeDatabase, sdk.AccountParameterMaxDataExtensionTimeInDays), + StringParameterValueComputedIf("external_volume", params, sdk.ParameterTypeDatabase, sdk.AccountParameterExternalVolume), + StringParameterValueComputedIf("catalog", params, sdk.ParameterTypeDatabase, sdk.AccountParameterCatalog), + BoolParameterValueComputedIf("replace_invalid_characters", params, sdk.ParameterTypeDatabase, sdk.AccountParameterReplaceInvalidCharacters), + StringParameterValueComputedIf("default_ddl_collation", params, sdk.ParameterTypeDatabase, sdk.AccountParameterDefaultDDLCollation), + StringParameterValueComputedIf("storage_serialization_policy", params, sdk.ParameterTypeDatabase, sdk.AccountParameterStorageSerializationPolicy), + StringParameterValueComputedIf("log_level", params, sdk.ParameterTypeDatabase, sdk.AccountParameterLogLevel), + StringParameterValueComputedIf("trace_level", params, sdk.ParameterTypeDatabase, sdk.AccountParameterTraceLevel), + IntParameterValueComputedIf("suspend_task_after_num_failures", params, sdk.ParameterTypeDatabase, sdk.AccountParameterSuspendTaskAfterNumFailures), + IntParameterValueComputedIf("task_auto_retry_attempts", params, sdk.ParameterTypeDatabase, sdk.AccountParameterTaskAutoRetryAttempts), + StringParameterValueComputedIf("user_task_managed_initial_warehouse_size", params, sdk.ParameterTypeDatabase, sdk.AccountParameterUserTaskManagedInitialWarehouseSize), + IntParameterValueComputedIf("user_task_timeout_ms", params, sdk.ParameterTypeDatabase, sdk.AccountParameterUserTaskTimeoutMs), + IntParameterValueComputedIf("user_task_minimum_trigger_interval_in_seconds", params, sdk.ParameterTypeDatabase, sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds), + BoolParameterValueComputedIf("quoted_identifiers_ignore_case", params, sdk.ParameterTypeDatabase, sdk.AccountParameterQuotedIdentifiersIgnoreCase), + BoolParameterValueComputedIf("enable_console_output", params, sdk.ParameterTypeDatabase, sdk.AccountParameterEnableConsoleOutput), )(ctx, d, meta) } ) @@ -147,20 +144,11 @@ func init() { ValidateDiag: validation.ToDiagFunc(validation.IntAtLeast(0)), }, { - Name: sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, - Type: schema.TypeString, - Description: "The initial size of warehouse to use for managed warehouses in the absence of history.", - DiffSuppress: func(k, old, new string, d *schema.ResourceData) bool { - oldSize, err := sdk.ToWarehouseSize(old) - if err != nil { - return false - } - newSize, err := sdk.ToWarehouseSize(new) - if err != nil { - return false - } - return oldSize == newSize - }, + Name: sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, + Type: schema.TypeString, + Description: "The initial size of warehouse to use for managed warehouses in the absence of history.", + ValidateDiag: sdkValidation(sdk.ToWarehouseSize), + DiffSuppress: NormalizeAndCompare(sdk.ToWarehouseSize), }, { Name: sdk.ObjectParameterUserTaskTimeoutMs, @@ -212,6 +200,7 @@ func init() { } } +// TODO(SNOW-1480106): Change to smaller and safer return type func GetAllDatabaseParameters(d *schema.ResourceData) ( dataRetentionTimeInDays *int, maxDataExtensionTimeInDays *int, @@ -229,6 +218,7 @@ func GetAllDatabaseParameters(d *schema.ResourceData) ( userTaskMinimumTriggerIntervalInSeconds *int, quotedIdentifiersIgnoreCase *bool, enableConsoleOutput *bool, + err error, ) { dataRetentionTimeInDays = GetPropertyAsPointer[int](d, "data_retention_time_in_days") maxDataExtensionTimeInDays = GetPropertyAsPointer[int](d, "max_data_extension_time_in_days") @@ -252,7 +242,11 @@ func GetAllDatabaseParameters(d *schema.ResourceData) ( suspendTaskAfterNumFailures = GetPropertyAsPointer[int](d, "suspend_task_after_num_failures") taskAutoRetryAttempts = GetPropertyAsPointer[int](d, "task_auto_retry_attempts") if userTaskManagedInitialWarehouseSizeRaw := GetPropertyAsPointer[string](d, "user_task_managed_initial_warehouse_size"); userTaskManagedInitialWarehouseSizeRaw != nil { - userTaskManagedInitialWarehouseSize = sdk.Pointer(sdk.WarehouseSize(*userTaskManagedInitialWarehouseSizeRaw)) + var warehouseSize sdk.WarehouseSize + if warehouseSize, err = sdk.ToWarehouseSize(*userTaskManagedInitialWarehouseSizeRaw); err != nil { + return + } + userTaskManagedInitialWarehouseSize = sdk.Pointer(warehouseSize) } userTaskTimeoutMs = GetPropertyAsPointer[int](d, "user_task_timeout_ms") userTaskMinimumTriggerIntervalInSeconds = GetPropertyAsPointer[int](d, "user_task_minimum_trigger_interval_in_seconds") diff --git a/pkg/resources/database_state_upgraders.go b/pkg/resources/database_state_upgraders.go index 2cecbaf1eb..df04f75d13 100644 --- a/pkg/resources/database_state_upgraders.go +++ b/pkg/resources/database_state_upgraders.go @@ -27,13 +27,3 @@ func v092DatabaseStateUpgrader(ctx context.Context, rawState map[string]any, met return rawState, nil } - -// resource.TestCheckResourceAttr("snowflake_database.test", "replication_configuration.#", "1"), -// resource.TestCheckResourceAttr("snowflake_database.test", "replication_configuration.0.ignore_edition_check", "true"), -// resource.TestCheckResourceAttr("snowflake_database.test", "replication_configuration.0.accounts.#", "1"), -// resource.TestCheckResourceAttr("snowflake_database.test", "replication_configuration.0.accounts.0", secondaryAccountIdentifier), - -// resource.TestCheckResourceAttr("snowflake_database.test", "replication.0.ignore_edition_check", "true"), -// resource.TestCheckResourceAttr("snowflake_database.test", "replication.0.enable_to_account.#", "1"), -// resource.TestCheckResourceAttr("snowflake_database.test", "replication.0.enable_to_account.0.account_identifier", secondaryAccountIdentifier), -// resource.TestCheckResourceAttr("snowflake_database.test", "replication.0.enable_to_account.0.with_failover", "false"), diff --git a/pkg/resources/helpers.go b/pkg/resources/helpers.go index 4aea34666b..70315b087f 100644 --- a/pkg/resources/helpers.go +++ b/pkg/resources/helpers.go @@ -293,10 +293,13 @@ func MergeMaps[M ~map[K]V, K comparable, V any](src ...M) M { return merged } +// TODO(SNOW-1479870): Test +// JoinDiags iterates through passed diag.Diagnostics and joins them into one diag.Diagnostics. +// If none of the passed diagnostics contained any element a nil reference will be returned. func JoinDiags(diagnostics ...diag.Diagnostics) diag.Diagnostics { var result diag.Diagnostics for _, diagnostic := range diagnostics { - if diagnostic != nil { + if len(diagnostic) > 0 { result = append(result, diagnostic...) } } diff --git a/pkg/resources/helpers_test.go b/pkg/resources/helpers_test.go index a1303204ef..dabf7bbfc6 100644 --- a/pkg/resources/helpers_test.go +++ b/pkg/resources/helpers_test.go @@ -237,6 +237,13 @@ func TestListDiff(t *testing.T) { Added []any Removed []any }{ + { + Name: "no changes", + Before: []any{1, 2, 3, 4}, + After: []any{1, 2, 3, 4}, + Removed: []any{}, + Added: []any{}, + }, { Name: "only removed", Before: []any{1, 2, 3, 4}, diff --git a/pkg/resources/secondary_database.go b/pkg/resources/secondary_database.go index 6813adb1dd..f66f800042 100644 --- a/pkg/resources/secondary_database.go +++ b/pkg/resources/secondary_database.go @@ -74,9 +74,13 @@ func CreateSecondaryDatabase(ctx context.Context, d *schema.ResourceData, meta a userTaskTimeoutMs, userTaskMinimumTriggerIntervalInSeconds, quotedIdentifiersIgnoreCase, - enableConsoleOutput := GetAllDatabaseParameters(d) + enableConsoleOutput, + err := GetAllDatabaseParameters(d) + if err != nil { + return diag.FromErr(err) + } - err := client.Databases.CreateSecondary(ctx, secondaryDatabaseId, primaryDatabaseId, &sdk.CreateSecondaryDatabaseOptions{ + err = client.Databases.CreateSecondary(ctx, secondaryDatabaseId, primaryDatabaseId, &sdk.CreateSecondaryDatabaseOptions{ Transient: GetPropertyAsPointer[bool](d, "is_transient"), DataRetentionTimeInDays: dataRetentionTimeInDays, MaxDataExtensionTimeInDays: maxDataExtensionTimeInDays, diff --git a/pkg/resources/secondary_database_acceptance_test.go b/pkg/resources/secondary_database_acceptance_test.go index 058b166522..fccc1683f1 100644 --- a/pkg/resources/secondary_database_acceptance_test.go +++ b/pkg/resources/secondary_database_acceptance_test.go @@ -2,9 +2,10 @@ package resources_test import ( "context" - "slices" "testing" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers" + acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" @@ -27,37 +28,24 @@ func TestAcc_CreateSecondaryDatabase_Basic(t *testing.T) { newId := acc.TestClient().Ids.RandomAccountObjectIdentifier() newComment := random.Comment() - params, err := acc.Client(t).Parameters.ShowParameters(context.Background(), &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Account: sdk.Bool(true), - }, - }) - require.NoError(t, err) - - findParamValue := func(searchedParameter sdk.AccountParameter) string { - idx := slices.IndexFunc(params, func(parameter *sdk.Parameter) bool { - return parameter.Key == string(searchedParameter) - }) - require.NotEqual(t, -1, idx, string(searchedParameter)) - return params[idx].Value - } - - accountDataRetentionTimeInDays := findParamValue(sdk.AccountParameterDataRetentionTimeInDays) - accountMaxDataExtensionTimeInDays := findParamValue(sdk.AccountParameterMaxDataExtensionTimeInDays) - accountExternalVolume := findParamValue(sdk.AccountParameterExternalVolume) - accountCatalog := findParamValue(sdk.AccountParameterCatalog) - accountReplaceInvalidCharacters := findParamValue(sdk.AccountParameterReplaceInvalidCharacters) - accountDefaultDdlCollation := findParamValue(sdk.AccountParameterDefaultDDLCollation) - accountStorageSerializationPolicy := findParamValue(sdk.AccountParameterStorageSerializationPolicy) - accountLogLevel := findParamValue(sdk.AccountParameterLogLevel) - accountTraceLevel := findParamValue(sdk.AccountParameterTraceLevel) - accountSuspendTaskAfterNumFailures := findParamValue(sdk.AccountParameterSuspendTaskAfterNumFailures) - accountTaskAutoRetryAttempts := findParamValue(sdk.AccountParameterTaskAutoRetryAttempts) - accountUserTaskMangedInitialWarehouseSize := findParamValue(sdk.AccountParameterUserTaskManagedInitialWarehouseSize) - accountUserTaskTimeoutMs := findParamValue(sdk.AccountParameterUserTaskTimeoutMs) - accountUserTaskMinimumTriggerIntervalInSeconds := findParamValue(sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds) - accountQuotedIdentifiersIgnoreCase := findParamValue(sdk.AccountParameterQuotedIdentifiersIgnoreCase) - accountEnableConsoleOutput := findParamValue(sdk.AccountParameterEnableConsoleOutput) + var ( + accountDataRetentionTimeInDays = new(string) + accountMaxDataExtensionTimeInDays = new(string) + accountExternalVolume = new(string) + accountCatalog = new(string) + accountReplaceInvalidCharacters = new(string) + accountDefaultDdlCollation = new(string) + accountStorageSerializationPolicy = new(string) + accountLogLevel = new(string) + accountTraceLevel = new(string) + accountSuspendTaskAfterNumFailures = new(string) + accountTaskAutoRetryAttempts = new(string) + accountUserTaskMangedInitialWarehouseSize = new(string) + accountUserTaskTimeoutMs = new(string) + accountUserTaskMinimumTriggerIntervalInSeconds = new(string) + accountQuotedIdentifiersIgnoreCase = new(string) + accountEnableConsoleOutput = new(string) + ) configVariables := func(id sdk.AccountObjectIdentifier, primaryDatabaseName sdk.ExternalObjectIdentifier, comment string) config.Variables { return config.Variables{ @@ -76,6 +64,25 @@ func TestAcc_CreateSecondaryDatabase_Basic(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.SharedDatabase), Steps: []resource.TestStep{ { + PreConfig: func() { + params := acc.TestClient().Parameter.ShowAccountParameters(t) + *accountDataRetentionTimeInDays = helpers.FindParameter(t, params, sdk.AccountParameterDataRetentionTimeInDays).Value + *accountMaxDataExtensionTimeInDays = helpers.FindParameter(t, params, sdk.AccountParameterMaxDataExtensionTimeInDays).Value + *accountExternalVolume = helpers.FindParameter(t, params, sdk.AccountParameterExternalVolume).Value + *accountCatalog = helpers.FindParameter(t, params, sdk.AccountParameterCatalog).Value + *accountReplaceInvalidCharacters = helpers.FindParameter(t, params, sdk.AccountParameterReplaceInvalidCharacters).Value + *accountDefaultDdlCollation = helpers.FindParameter(t, params, sdk.AccountParameterDefaultDDLCollation).Value + *accountStorageSerializationPolicy = helpers.FindParameter(t, params, sdk.AccountParameterStorageSerializationPolicy).Value + *accountLogLevel = helpers.FindParameter(t, params, sdk.AccountParameterLogLevel).Value + *accountTraceLevel = helpers.FindParameter(t, params, sdk.AccountParameterTraceLevel).Value + *accountSuspendTaskAfterNumFailures = helpers.FindParameter(t, params, sdk.AccountParameterSuspendTaskAfterNumFailures).Value + *accountTaskAutoRetryAttempts = helpers.FindParameter(t, params, sdk.AccountParameterTaskAutoRetryAttempts).Value + *accountUserTaskMangedInitialWarehouseSize = helpers.FindParameter(t, params, sdk.AccountParameterUserTaskManagedInitialWarehouseSize).Value + *accountUserTaskTimeoutMs = helpers.FindParameter(t, params, sdk.AccountParameterUserTaskTimeoutMs).Value + *accountUserTaskMinimumTriggerIntervalInSeconds = helpers.FindParameter(t, params, sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds).Value + *accountQuotedIdentifiersIgnoreCase = helpers.FindParameter(t, params, sdk.AccountParameterQuotedIdentifiersIgnoreCase).Value + *accountEnableConsoleOutput = helpers.FindParameter(t, params, sdk.AccountParameterEnableConsoleOutput).Value + }, ConfigVariables: configVariables(id, externalPrimaryId, comment), ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecondaryDatabase/basic"), Check: resource.ComposeTestCheckFunc( @@ -83,22 +90,22 @@ func TestAcc_CreateSecondaryDatabase_Basic(t *testing.T) { resource.TestCheckResourceAttr("snowflake_secondary_database.test", "as_replica_of", externalPrimaryId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_secondary_database.test", "comment", comment), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "data_retention_time_in_days", accountDataRetentionTimeInDays), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "max_data_extension_time_in_days", accountMaxDataExtensionTimeInDays), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "external_volume", accountExternalVolume), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "catalog", accountCatalog), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "replace_invalid_characters", accountReplaceInvalidCharacters), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "default_ddl_collation", accountDefaultDdlCollation), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "storage_serialization_policy", accountStorageSerializationPolicy), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "log_level", accountLogLevel), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "trace_level", accountTraceLevel), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "suspend_task_after_num_failures", accountSuspendTaskAfterNumFailures), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "task_auto_retry_attempts", accountTaskAutoRetryAttempts), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_managed_initial_warehouse_size", accountUserTaskMangedInitialWarehouseSize), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_timeout_ms", accountUserTaskTimeoutMs), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_minimum_trigger_interval_in_seconds", accountUserTaskMinimumTriggerIntervalInSeconds), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "quoted_identifiers_ignore_case", accountQuotedIdentifiersIgnoreCase), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "enable_console_output", accountEnableConsoleOutput), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "data_retention_time_in_days", accountDataRetentionTimeInDays), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "max_data_extension_time_in_days", accountMaxDataExtensionTimeInDays), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "external_volume", accountExternalVolume), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "catalog", accountCatalog), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "replace_invalid_characters", accountReplaceInvalidCharacters), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "default_ddl_collation", accountDefaultDdlCollation), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "storage_serialization_policy", accountStorageSerializationPolicy), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "log_level", accountLogLevel), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "trace_level", accountTraceLevel), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "suspend_task_after_num_failures", accountSuspendTaskAfterNumFailures), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "task_auto_retry_attempts", accountTaskAutoRetryAttempts), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_managed_initial_warehouse_size", accountUserTaskMangedInitialWarehouseSize), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_timeout_ms", accountUserTaskTimeoutMs), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_minimum_trigger_interval_in_seconds", accountUserTaskMinimumTriggerIntervalInSeconds), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "quoted_identifiers_ignore_case", accountQuotedIdentifiersIgnoreCase), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "enable_console_output", accountEnableConsoleOutput), ), }, // Rename + comment update @@ -110,22 +117,22 @@ func TestAcc_CreateSecondaryDatabase_Basic(t *testing.T) { resource.TestCheckResourceAttr("snowflake_secondary_database.test", "as_replica_of", externalPrimaryId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_secondary_database.test", "comment", newComment), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "data_retention_time_in_days", accountDataRetentionTimeInDays), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "max_data_extension_time_in_days", accountMaxDataExtensionTimeInDays), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "external_volume", accountExternalVolume), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "catalog", accountCatalog), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "replace_invalid_characters", accountReplaceInvalidCharacters), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "default_ddl_collation", accountDefaultDdlCollation), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "storage_serialization_policy", accountStorageSerializationPolicy), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "log_level", accountLogLevel), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "trace_level", accountTraceLevel), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "suspend_task_after_num_failures", accountSuspendTaskAfterNumFailures), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "task_auto_retry_attempts", accountTaskAutoRetryAttempts), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_managed_initial_warehouse_size", accountUserTaskMangedInitialWarehouseSize), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_timeout_ms", accountUserTaskTimeoutMs), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_minimum_trigger_interval_in_seconds", accountUserTaskMinimumTriggerIntervalInSeconds), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "quoted_identifiers_ignore_case", accountQuotedIdentifiersIgnoreCase), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "enable_console_output", accountEnableConsoleOutput), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "data_retention_time_in_days", accountDataRetentionTimeInDays), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "max_data_extension_time_in_days", accountMaxDataExtensionTimeInDays), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "external_volume", accountExternalVolume), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "catalog", accountCatalog), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "replace_invalid_characters", accountReplaceInvalidCharacters), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "default_ddl_collation", accountDefaultDdlCollation), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "storage_serialization_policy", accountStorageSerializationPolicy), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "log_level", accountLogLevel), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "trace_level", accountTraceLevel), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "suspend_task_after_num_failures", accountSuspendTaskAfterNumFailures), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "task_auto_retry_attempts", accountTaskAutoRetryAttempts), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_managed_initial_warehouse_size", accountUserTaskMangedInitialWarehouseSize), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_timeout_ms", accountUserTaskTimeoutMs), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_minimum_trigger_interval_in_seconds", accountUserTaskMinimumTriggerIntervalInSeconds), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "quoted_identifiers_ignore_case", accountQuotedIdentifiersIgnoreCase), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "enable_console_output", accountEnableConsoleOutput), ), }, // Import all values @@ -164,37 +171,24 @@ func TestAcc_CreateSecondaryDatabase_complete(t *testing.T) { newCatalogId, newCatalogCleanup := acc.TestClient().CatalogIntegration.Create(t) t.Cleanup(newCatalogCleanup) - params, err := acc.Client(t).Parameters.ShowParameters(context.Background(), &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Account: sdk.Bool(true), - }, - }) - require.NoError(t, err) - - findParamValue := func(searchedParameter sdk.AccountParameter) string { - idx := slices.IndexFunc(params, func(parameter *sdk.Parameter) bool { - return parameter.Key == string(searchedParameter) - }) - require.NotEqual(t, -1, idx, string(searchedParameter)) - return params[idx].Value - } - - accountDataRetentionTimeInDays := findParamValue(sdk.AccountParameterDataRetentionTimeInDays) - accountMaxDataExtensionTimeInDays := findParamValue(sdk.AccountParameterMaxDataExtensionTimeInDays) - accountExternalVolume := findParamValue(sdk.AccountParameterExternalVolume) - accountCatalog := findParamValue(sdk.AccountParameterCatalog) - accountReplaceInvalidCharacters := findParamValue(sdk.AccountParameterReplaceInvalidCharacters) - accountDefaultDdlCollation := findParamValue(sdk.AccountParameterDefaultDDLCollation) - accountStorageSerializationPolicy := findParamValue(sdk.AccountParameterStorageSerializationPolicy) - accountLogLevel := findParamValue(sdk.AccountParameterLogLevel) - accountTraceLevel := findParamValue(sdk.AccountParameterTraceLevel) - accountSuspendTaskAfterNumFailures := findParamValue(sdk.AccountParameterSuspendTaskAfterNumFailures) - accountTaskAutoRetryAttempts := findParamValue(sdk.AccountParameterTaskAutoRetryAttempts) - accountUserTaskMangedInitialWarehouseSize := findParamValue(sdk.AccountParameterUserTaskManagedInitialWarehouseSize) - accountUserTaskTimeoutMs := findParamValue(sdk.AccountParameterUserTaskTimeoutMs) - accountUserTaskMinimumTriggerIntervalInSeconds := findParamValue(sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds) - accountQuotedIdentifiersIgnoreCase := findParamValue(sdk.AccountParameterQuotedIdentifiersIgnoreCase) - accountEnableConsoleOutput := findParamValue(sdk.AccountParameterEnableConsoleOutput) + var ( + accountDataRetentionTimeInDays = new(string) + accountMaxDataExtensionTimeInDays = new(string) + accountExternalVolume = new(string) + accountCatalog = new(string) + accountReplaceInvalidCharacters = new(string) + accountDefaultDdlCollation = new(string) + accountStorageSerializationPolicy = new(string) + accountLogLevel = new(string) + accountTraceLevel = new(string) + accountSuspendTaskAfterNumFailures = new(string) + accountTaskAutoRetryAttempts = new(string) + accountUserTaskMangedInitialWarehouseSize = new(string) + accountUserTaskTimeoutMs = new(string) + accountUserTaskMinimumTriggerIntervalInSeconds = new(string) + accountQuotedIdentifiersIgnoreCase = new(string) + accountEnableConsoleOutput = new(string) + ) unsetConfigVariables := config.Variables{ "name": config.StringVariable(id.Name()), @@ -256,6 +250,25 @@ func TestAcc_CreateSecondaryDatabase_complete(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.SecondaryDatabase), Steps: []resource.TestStep{ { + PreConfig: func() { + params := acc.TestClient().Parameter.ShowAccountParameters(t) + *accountDataRetentionTimeInDays = helpers.FindParameter(t, params, sdk.AccountParameterDataRetentionTimeInDays).Value + *accountMaxDataExtensionTimeInDays = helpers.FindParameter(t, params, sdk.AccountParameterMaxDataExtensionTimeInDays).Value + *accountExternalVolume = helpers.FindParameter(t, params, sdk.AccountParameterExternalVolume).Value + *accountCatalog = helpers.FindParameter(t, params, sdk.AccountParameterCatalog).Value + *accountReplaceInvalidCharacters = helpers.FindParameter(t, params, sdk.AccountParameterReplaceInvalidCharacters).Value + *accountDefaultDdlCollation = helpers.FindParameter(t, params, sdk.AccountParameterDefaultDDLCollation).Value + *accountStorageSerializationPolicy = helpers.FindParameter(t, params, sdk.AccountParameterStorageSerializationPolicy).Value + *accountLogLevel = helpers.FindParameter(t, params, sdk.AccountParameterLogLevel).Value + *accountTraceLevel = helpers.FindParameter(t, params, sdk.AccountParameterTraceLevel).Value + *accountSuspendTaskAfterNumFailures = helpers.FindParameter(t, params, sdk.AccountParameterSuspendTaskAfterNumFailures).Value + *accountTaskAutoRetryAttempts = helpers.FindParameter(t, params, sdk.AccountParameterTaskAutoRetryAttempts).Value + *accountUserTaskMangedInitialWarehouseSize = helpers.FindParameter(t, params, sdk.AccountParameterUserTaskManagedInitialWarehouseSize).Value + *accountUserTaskTimeoutMs = helpers.FindParameter(t, params, sdk.AccountParameterUserTaskTimeoutMs).Value + *accountUserTaskMinimumTriggerIntervalInSeconds = helpers.FindParameter(t, params, sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds).Value + *accountQuotedIdentifiersIgnoreCase = helpers.FindParameter(t, params, sdk.AccountParameterQuotedIdentifiersIgnoreCase).Value + *accountEnableConsoleOutput = helpers.FindParameter(t, params, sdk.AccountParameterEnableConsoleOutput).Value + }, ConfigVariables: setConfigVariables, ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecondaryDatabase/complete-optionals-set"), Check: resource.ComposeTestCheckFunc( @@ -318,22 +331,22 @@ func TestAcc_CreateSecondaryDatabase_complete(t *testing.T) { resource.TestCheckResourceAttr("snowflake_secondary_database.test", "as_replica_of", externalPrimaryId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_secondary_database.test", "comment", newComment), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "data_retention_time_in_days.0.value", accountDataRetentionTimeInDays), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "max_data_extension_time_in_days.0.value", accountMaxDataExtensionTimeInDays), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "external_volume", accountExternalVolume), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "catalog", accountCatalog), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "replace_invalid_characters", accountReplaceInvalidCharacters), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "default_ddl_collation", accountDefaultDdlCollation), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "storage_serialization_policy", accountStorageSerializationPolicy), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "log_level", accountLogLevel), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "trace_level", accountTraceLevel), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "suspend_task_after_num_failures", accountSuspendTaskAfterNumFailures), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "task_auto_retry_attempts", accountTaskAutoRetryAttempts), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_managed_initial_warehouse_size", accountUserTaskMangedInitialWarehouseSize), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_timeout_ms", accountUserTaskTimeoutMs), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "user_task_minimum_trigger_interval_in_seconds", accountUserTaskMinimumTriggerIntervalInSeconds), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "quoted_identifiers_ignore_case", accountQuotedIdentifiersIgnoreCase), - resource.TestCheckResourceAttr("snowflake_secondary_database.test", "enable_console_output", accountEnableConsoleOutput), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "data_retention_time_in_days.0.value", accountDataRetentionTimeInDays), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "max_data_extension_time_in_days.0.value", accountMaxDataExtensionTimeInDays), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "external_volume", accountExternalVolume), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "catalog", accountCatalog), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "replace_invalid_characters", accountReplaceInvalidCharacters), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "default_ddl_collation", accountDefaultDdlCollation), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "storage_serialization_policy", accountStorageSerializationPolicy), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "log_level", accountLogLevel), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "trace_level", accountTraceLevel), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "suspend_task_after_num_failures", accountSuspendTaskAfterNumFailures), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "task_auto_retry_attempts", accountTaskAutoRetryAttempts), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_managed_initial_warehouse_size", accountUserTaskMangedInitialWarehouseSize), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_timeout_ms", accountUserTaskTimeoutMs), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "user_task_minimum_trigger_interval_in_seconds", accountUserTaskMinimumTriggerIntervalInSeconds), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "quoted_identifiers_ignore_case", accountQuotedIdentifiersIgnoreCase), + resource.TestCheckResourceAttrPtr("snowflake_secondary_database.test", "enable_console_output", accountEnableConsoleOutput), ), }, { diff --git a/pkg/resources/shared_database.go b/pkg/resources/shared_database.go index 632d01cf99..28855b66e2 100644 --- a/pkg/resources/shared_database.go +++ b/pkg/resources/shared_database.go @@ -72,9 +72,13 @@ func CreateSharedDatabase(ctx context.Context, d *schema.ResourceData, meta any) userTaskTimeoutMs, userTaskMinimumTriggerIntervalInSeconds, quotedIdentifiersIgnoreCase, - enableConsoleOutput := GetAllDatabaseParameters(d) + enableConsoleOutput, + err := GetAllDatabaseParameters(d) + if err != nil { + return diag.FromErr(err) + } - err := client.Databases.CreateShared(ctx, id, externalShareId, &sdk.CreateSharedDatabaseOptions{ + err = client.Databases.CreateShared(ctx, id, externalShareId, &sdk.CreateSharedDatabaseOptions{ // TODO(SNOW-1325381) // Transient: GetPropertyAsPointer[bool](d, "is_transient"), ExternalVolume: externalVolume,