diff --git a/pkg/resources/database.go b/pkg/resources/database.go index 275cb3b2fa..d30b7ec0c5 100644 --- a/pkg/resources/database.go +++ b/pkg/resources/database.go @@ -263,16 +263,25 @@ func UpdateDatabase(d *schema.ResourceData, meta interface{}) error { // If replication configuration changes, need to update accounts that have permission to replicate database if d.HasChange("replication_configuration") { oldConfig, newConfig := d.GetChange("replication_configuration") - newAccounts := newConfig.([]interface{})[0].(map[string]interface{})["accounts"].([]interface{}) - newAccountIDs := make([]sdk.AccountIdentifier, len(newAccounts)) - for i, account := range newAccounts { - newAccountIDs[i] = sdk.NewAccountIdentifierFromAccountLocator(account.(string)) + + newAccountIDs := make([]sdk.AccountIdentifier, 0) + ignoreEditionCheck := false + if len(newConfig.([]interface{})) != 0 { + newAccounts := newConfig.([]interface{})[0].(map[string]interface{})["accounts"].([]interface{}) + for _, account := range newAccounts { + newAccountIDs = append(newAccountIDs, sdk.NewAccountIdentifierFromAccountLocator(account.(string))) + } + ignoreEditionCheck = newConfig.([]interface{})[0].(map[string]interface{})["ignore_edition_check"].(bool) } - oldAccounts := oldConfig.([]interface{})[0].(map[string]interface{})["accounts"].([]interface{}) - oldAccountIDs := make([]sdk.AccountIdentifier, len(oldAccounts)) - for i, account := range oldAccounts { - oldAccountIDs[i] = sdk.NewAccountIdentifierFromAccountLocator(account.(string)) + + oldAccountIDs := make([]sdk.AccountIdentifier, 0) + if len(oldConfig.([]interface{})) != 0 { + oldAccounts := oldConfig.([]interface{})[0].(map[string]interface{})["accounts"].([]interface{}) + for _, account := range oldAccounts { + oldAccountIDs = append(oldAccountIDs, sdk.NewAccountIdentifierFromAccountLocator(account.(string))) + } } + accountsToRemove := make([]sdk.AccountIdentifier, 0) accountsToAdd := make([]sdk.AccountIdentifier, 0) // Find accounts to remove @@ -294,7 +303,7 @@ func UpdateDatabase(d *schema.ResourceData, meta interface{}) error { ToAccounts: accountsToAdd, }, } - if ignoreEditionCheck := d.Get("ignore_edition_check").(bool); ignoreEditionCheck { + if ignoreEditionCheck { opts.EnableReplication.IgnoreEditionCheck = sdk.Bool(ignoreEditionCheck) } err := client.Databases.AlterReplication(ctx, id, opts) diff --git a/pkg/resources/database_acceptance_test.go b/pkg/resources/database_acceptance_test.go index 21b20c506f..a5e7f22b29 100644 --- a/pkg/resources/database_acceptance_test.go +++ b/pkg/resources/database_acceptance_test.go @@ -49,6 +49,8 @@ func TestAcc_Database(t *testing.T) { prefix := "tst-terraform" + strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) prefix2 := "tst-terraform" + strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) + secondaryAccountName := getSecondaryAccount(t) + resource.ParallelTest(t, resource.TestCase{ Providers: acc.TestAccProviders(), PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -80,11 +82,25 @@ func TestAcc_Database(t *testing.T) { resource.TestCheckResourceAttr("snowflake_database.db", "data_retention_time_in_days", "3"), ), }, + // ADD REPLICATION + // proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2369 error + { + Config: dbConfigWithReplication(prefix2, secondaryAccountName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_database.db", "name", prefix2), + resource.TestCheckResourceAttr("snowflake_database.db", "comment", "test comment 2"), + resource.TestCheckResourceAttr("snowflake_database.db", "data_retention_time_in_days", "3"), + resource.TestCheckResourceAttr("snowflake_database.db", "replication_configuration.#", "1"), + resource.TestCheckResourceAttr("snowflake_database.db", "replication_configuration.0.accounts.#", "1"), + resource.TestCheckResourceAttr("snowflake_database.db", "replication_configuration.0.accounts.0", secondaryAccountName), + ), + }, // IMPORT { - ResourceName: "snowflake_database.db", - ImportState: true, - ImportStateVerify: true, + ResourceName: "snowflake_database.db", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"replication_configuration"}, }, }, }) @@ -155,6 +171,22 @@ resource "snowflake_database" "db" { return fmt.Sprintf(s, prefix) } +func dbConfigWithReplication(prefix string, secondaryAccountName string) string { + s := ` +resource "snowflake_database" "db" { + name = "%s" + comment = "test comment 2" + data_retention_time_in_days = 3 + replication_configuration { + accounts = [ + "%s" + ] + } +} +` + return fmt.Sprintf(s, prefix, secondaryAccountName) +} + func dropDatabaseOutsideTerraform(t *testing.T, id string) { t.Helper() @@ -166,6 +198,23 @@ func dropDatabaseOutsideTerraform(t *testing.T, id string) { require.NoError(t, err) } +func getSecondaryAccount(t *testing.T) string { + t.Helper() + + secondaryConfig, err := sdk.ProfileConfig("secondary_test_account") + require.NoError(t, err) + + secondaryClient, err := sdk.NewClient(secondaryConfig) + require.NoError(t, err) + + ctx := context.Background() + + account, err := secondaryClient.ContextFunctions.CurrentAccount(ctx) + require.NoError(t, err) + + return account +} + func testAccCheckDatabaseExistence(t *testing.T, id string, shouldExist bool) func(state *terraform.State) error { t.Helper() return func(state *terraform.State) error {