From 048725fb9b6936a0e7fc9dff2d7c00615f6a2218 Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 6 Nov 2024 17:01:33 +0100 Subject: [PATCH] Adapt user resource to BCR Bundle 2024_08 References: #3125 --- MIGRATION_GUIDE.md | 8 + .../resourceassert/user_resource_ext.go | 28 +++ pkg/resources/user_acceptance_test.go | 171 ++++++++++++++++++ pkg/sdk/users.go | 24 ++- 4 files changed, 223 insertions(+), 8 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 5a79d9cc50..2d39ac4327 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -159,6 +159,14 @@ This segregation was based on the secret flows in CREATE SECRET. i.e.: See reference [docs](https://docs.snowflake.com/en/sql-reference/sql/create-secret). +### *(bugfix)* Handle BCR Bundle 2024_08 in snowflake_user resource + +[bcr 2024_08](https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_08/bcr-1798) changed the "empty" response in the `SHOW USERS` query. This provider version adapts to the new result types; it should be used if you want to have 2024_08 Bundle enabled on your account. + +Note: Because [bcr 2024_07](https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_07/bcr-1692) changes the way how the `default_secondary_roles` attribute behaves, drift may be reported when enabling 2024_08 Bundle. Check [Handling default secondary roles](#breaking-change-handling-default-secondary-roles) for more context. + +Connected issues: [#3125](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3125) + ## v0.96.0 ➞ v0.97.0 ### *(new feature)* snowflake_stream_on_table, snowflake_stream_on_external_table resource diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_ext.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_ext.go index 076102926f..5fd51745bb 100644 --- a/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_ext.go +++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_ext.go @@ -3,6 +3,8 @@ package resourceassert import ( "strconv" + r "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/resources" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" ) @@ -25,3 +27,29 @@ func (u *UserResourceAssert) HasMustChangePassword(expected bool) *UserResourceA func (u *UserResourceAssert) HasDefaultSecondaryRolesOption(expected sdk.SecondaryRolesOption) *UserResourceAssert { return u.HasDefaultSecondaryRolesOptionString(string(expected)) } + +func (u *UserResourceAssert) HasAllDefaults(userId sdk.AccountObjectIdentifier, expectedDefaultSecondaryRoles sdk.SecondaryRolesOption) *UserResourceAssert { + return u. + HasNameString(userId.Name()). + HasNoPassword(). + HasNoLoginName(). + HasNoDisplayName(). + HasNoFirstName(). + HasNoMiddleName(). + HasNoLastName(). + HasNoEmail(). + HasMustChangePasswordString(r.BooleanDefault). + HasDisabledString(r.BooleanDefault). + HasNoDaysToExpiry(). + HasMinsToUnlockString(r.IntDefaultString). + HasNoDefaultWarehouse(). + HasNoDefaultNamespace(). + HasNoDefaultRole(). + HasDefaultSecondaryRolesOption(expectedDefaultSecondaryRoles). + HasMinsToBypassMfaString(r.IntDefaultString). + HasNoRsaPublicKey(). + HasNoRsaPublicKey2(). + HasNoComment(). + HasDisableMfaString(r.BooleanDefault). + HasFullyQualifiedNameString(userId.FullyQualifiedName()) +} diff --git a/pkg/resources/user_acceptance_test.go b/pkg/resources/user_acceptance_test.go index dcf3266fa9..2b9386535b 100644 --- a/pkg/resources/user_acceptance_test.go +++ b/pkg/resources/user_acceptance_test.go @@ -1582,3 +1582,174 @@ func TestAcc_User_LoginNameAndDisplayName(t *testing.T) { }, }) } + +// https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_08/bcr-1798 +// https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3125 +func TestAcc_User_handleChangesToShowUsers_bcr202408_gh3125(t *testing.T) { + userId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + + userModelNoAttributes := model.User("w", userId.Name()) + userModelWithNoneDefaultSecondaryRoles := model.User("w", userId.Name()).WithDefaultSecondaryRolesOptionEnum(sdk.SecondaryRolesOptionNone) + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + PreCheck: func() { acc.TestAccPreCheck(t) }, + CheckDestroy: acc.CheckDestroy(t, resources.User), + Steps: []resource.TestStep{ + { + PreConfig: func() { + acc.TestClient().BcrBundles.EnableBcrBundle(t, "2024_08") + }, + Config: config.FromModel(t, userModelNoAttributes), + Check: assert.AssertThat(t, + resourceassert.UserResource(t, userModelNoAttributes.ResourceReference()). + HasAllDefaults(userId, sdk.SecondaryRolesOptionDefault), + ), + }, + { + Config: config.FromModel(t, userModelWithNoneDefaultSecondaryRoles), + Check: assert.AssertThat(t, + resourceassert.UserResource(t, userModelWithNoneDefaultSecondaryRoles.ResourceReference()). + HasAllDefaults(userId, sdk.SecondaryRolesOptionNone), + ), + }, + }, + }) +} + +// https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_08/bcr-1798 +// https://docs.snowflake.com/release-notes/bcr-bundles/2024_08/bcr-1692 +// https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3125 +func TestAcc_User_handleChangesToShowUsers_bcr202408_gh3125_withbcr202407(t *testing.T) { + userId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + + userModel := model.User("w", userId.Name()).WithDefaultSecondaryRolesOptionEnum(sdk.SecondaryRolesOptionNone) + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + PreCheck: func() { acc.TestAccPreCheck(t) }, + CheckDestroy: acc.CheckDestroy(t, resources.User), + Steps: []resource.TestStep{ + { + PreConfig: func() { + acc.TestClient().BcrBundles.EnableBcrBundle(t, "2024_07") + acc.TestClient().BcrBundles.EnableBcrBundle(t, "2024_08") + }, + Config: config.FromModel(t, userModel), + Check: assert.AssertThat(t, + resourceassert.UserResource(t, userModel.ResourceReference()). + HasAllDefaults(userId, sdk.SecondaryRolesOptionNone), + ), + }, + }, + }) +} + +// https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_08/bcr-1798 +// https://docs.snowflake.com/release-notes/bcr-bundles/2024_08/bcr-1692 +// https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3125 +func TestAcc_User_handleChangesToShowUsers_bcr202408_migration_bcr202407_enabled(t *testing.T) { + userId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + + userModel := model.User("w", userId.Name()) + + resource.Test(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + PreCheck: func() { acc.TestAccPreCheck(t) }, + CheckDestroy: acc.CheckDestroy(t, resources.User), + Steps: []resource.TestStep{ + { + PreConfig: func() { + acc.TestClient().BcrBundles.EnableBcrBundle(t, "2024_07") + }, + ExternalProviders: map[string]resource.ExternalProvider{ + "snowflake": { + VersionConstraint: "=0.97.0", + Source: "Snowflake-Labs/snowflake", + }, + }, + Config: config.FromModel(t, userModel), + Check: assert.AssertThat(t, + resourceassert.UserResource(t, userModel.ResourceReference()). + HasAllDefaults(userId, sdk.SecondaryRolesOptionDefault), + ), + }, + { + PreConfig: func() { + acc.TestClient().BcrBundles.EnableBcrBundle(t, "2024_08") + }, + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + Config: config.FromModel(t, userModel), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, + }, + Check: assert.AssertThat(t, + resourceassert.UserResource(t, userModel.ResourceReference()). + HasAllDefaults(userId, sdk.SecondaryRolesOptionDefault), + ), + }, + }, + }) +} + +// https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_08/bcr-1798 +// https://docs.snowflake.com/release-notes/bcr-bundles/2024_08/bcr-1692 +// https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3125 +func TestAcc_User_handleChangesToShowUsers_bcr202408_migration_bcr202407_disabled(t *testing.T) { + userId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + + userModel := model.User("w", userId.Name()) + + resource.Test(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + PreCheck: func() { acc.TestAccPreCheck(t) }, + CheckDestroy: acc.CheckDestroy(t, resources.User), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "snowflake": { + VersionConstraint: "=0.97.0", + Source: "Snowflake-Labs/snowflake", + }, + }, + Config: config.FromModel(t, userModel), + Check: assert.AssertThat(t, + resourceassert.UserResource(t, userModel.ResourceReference()). + HasAllDefaults(userId, sdk.SecondaryRolesOptionDefault), + ), + }, + { + PreConfig: func() { + acc.TestClient().BcrBundles.EnableBcrBundle(t, "2024_08") + }, + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + Config: config.FromModel(t, userModel), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + planchecks.ExpectDrift(userModel.ResourceReference(), "default_secondary_roles_option", sdk.String(string(sdk.SecondaryRolesOptionDefault)), sdk.String(string(sdk.SecondaryRolesOptionAll))), + planchecks.ExpectChange(userModel.ResourceReference(), "default_secondary_roles_option", tfjson.ActionUpdate, sdk.String(string(sdk.SecondaryRolesOptionAll)), sdk.String(string(sdk.SecondaryRolesOptionDefault))), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, + }, + Check: assert.AssertThat(t, + resourceassert.UserResource(t, userModel.ResourceReference()). + HasAllDefaults(userId, sdk.SecondaryRolesOptionDefault), + ), + }, + }, + }) +} diff --git a/pkg/sdk/users.go b/pkg/sdk/users.go index 263d80198e..9615aa8269 100644 --- a/pkg/sdk/users.go +++ b/pkg/sdk/users.go @@ -95,12 +95,12 @@ type userDBRow struct { MustChangePassword sql.NullString `db:"must_change_password"` SnowflakeLock sql.NullString `db:"snowflake_lock"` DefaultWarehouse sql.NullString `db:"default_warehouse"` - DefaultNamespace string `db:"default_namespace"` - DefaultRole string `db:"default_role"` + DefaultNamespace sql.NullString `db:"default_namespace"` + DefaultRole sql.NullString `db:"default_role"` DefaultSecondaryRoles string `db:"default_secondary_roles"` ExtAuthnDuo sql.NullString `db:"ext_authn_duo"` - ExtAuthnUid string `db:"ext_authn_uid"` - MinsToBypassMfa string `db:"mins_to_bypass_mfa"` + ExtAuthnUid sql.NullString `db:"ext_authn_uid"` + MinsToBypassMfa sql.NullString `db:"mins_to_bypass_mfa"` Owner string `db:"owner"` LastSuccessLogin sql.NullTime `db:"last_success_login"` ExpiresAtTime sql.NullTime `db:"expires_at_time"` @@ -116,11 +116,7 @@ func (row userDBRow) convert() *User { Name: row.Name, CreatedOn: row.CreatedOn, LoginName: row.LoginName, - DefaultNamespace: row.DefaultNamespace, - DefaultRole: row.DefaultRole, DefaultSecondaryRoles: row.DefaultSecondaryRoles, - ExtAuthnUid: row.ExtAuthnUid, - MinsToBypassMfa: row.MinsToBypassMfa, Owner: row.Owner, HasPassword: row.HasPassword, HasRsaPublicKey: row.HasRsaPublicKey, @@ -151,9 +147,21 @@ func (row userDBRow) convert() *User { handleNullableBoolString(row.MustChangePassword, &user.MustChangePassword) handleNullableBoolString(row.SnowflakeLock, &user.SnowflakeLock) handleNullableBoolString(row.ExtAuthnDuo, &user.ExtAuthnDuo) + if row.ExtAuthnUid.Valid { + user.ExtAuthnUid = row.ExtAuthnUid.String + } + if row.MinsToBypassMfa.Valid { + user.MinsToBypassMfa = row.MinsToBypassMfa.String + } if row.DefaultWarehouse.Valid { user.DefaultWarehouse = row.DefaultWarehouse.String } + if row.DefaultNamespace.Valid { + user.DefaultNamespace = row.DefaultNamespace.String + } + if row.DefaultRole.Valid { + user.DefaultRole = row.DefaultRole.String + } if row.LastSuccessLogin.Valid { user.LastSuccessLogin = row.LastSuccessLogin.Time }