From bf78390997417c82c2a3df74282ef0c3dd5e0c50 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Aug 2022 21:13:48 +0100 Subject: [PATCH 1/6] Fix state password and string state upgraders to populate min_upper (#302) --- internal/provider/resource_password.go | 2 ++ internal/provider/resource_string.go | 1 + 2 files changed, 3 insertions(+) diff --git a/internal/provider/resource_password.go b/internal/provider/resource_password.go index ada43b33..2d205ae9 100644 --- a/internal/provider/resource_password.go +++ b/internal/provider/resource_password.go @@ -193,6 +193,7 @@ func upgradePasswordStateV0toV2(ctx context.Context, req resource.UpgradeStateRe Number: passwordDataV0.Number, Numeric: passwordDataV0.Number, MinNumeric: passwordDataV0.MinNumeric, + MinUpper: passwordDataV0.MinUpper, MinLower: passwordDataV0.MinLower, MinSpecial: passwordDataV0.MinSpecial, OverrideSpecial: passwordDataV0.OverrideSpecial, @@ -246,6 +247,7 @@ func upgradePasswordStateV1toV2(ctx context.Context, req resource.UpgradeStateRe Number: passwordDataV1.Number, Numeric: passwordDataV1.Number, MinNumeric: passwordDataV1.MinNumeric, + MinUpper: passwordDataV1.MinUpper, MinLower: passwordDataV1.MinLower, MinSpecial: passwordDataV1.MinSpecial, OverrideSpecial: passwordDataV1.OverrideSpecial, diff --git a/internal/provider/resource_string.go b/internal/provider/resource_string.go index 320b3c04..cf0d1566 100644 --- a/internal/provider/resource_string.go +++ b/internal/provider/resource_string.go @@ -490,6 +490,7 @@ func upgradeStringStateV1toV2(ctx context.Context, req resource.UpgradeStateRequ Number: stringDataV1.Number, Numeric: stringDataV1.Number, MinNumeric: stringDataV1.MinNumeric, + MinUpper: stringDataV1.MinUpper, MinLower: stringDataV1.MinLower, MinSpecial: stringDataV1.MinSpecial, OverrideSpecial: stringDataV1.OverrideSpecial, From 3dfb736a1b1a13bd9b3fed91c2e897895def7620 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Aug 2022 21:16:08 +0100 Subject: [PATCH 2/6] Update CHANGELOG (#302) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4668ee7..fcd64245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 3.4.2 (unreleased) + +BUG FIXES: + +* resource/random_password: During upgrade state, ensure `min_upper` is populated ([302](https://github.com/hashicorp/terraform-provider-random/pull/302)). +* resource/random_string: During upgrade state, ensure `min_upper` is populated ([302](https://github.com/hashicorp/terraform-provider-random/pull/302)). + ## 3.4.1 (August 31, 2022) BUG FIXES: From 63d9459c7f92c531f92aa51d137f35357a6da189 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Aug 2022 22:01:25 +0100 Subject: [PATCH 3/6] Adding tests to verify behviour of state upgraders for password and string resources (#302) --- internal/provider/provider_test.go | 18 +++ internal/provider/resource_password_test.go | 157 ++++++++++++++++++++ internal/provider/resource_string_test.go | 74 +++++++++ 3 files changed, 249 insertions(+) diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 2c9c4302..579db5c4 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -13,6 +13,24 @@ func protoV5ProviderFactories() map[string]func() (tfprotov5.ProviderServer, err } } +func providerVersion221() map[string]resource.ExternalProvider { + return map[string]resource.ExternalProvider{ + "random": { + VersionConstraint: "2.2.1", + Source: "hashicorp/random", + }, + } +} + +func providerVersion320() map[string]resource.ExternalProvider { + return map[string]resource.ExternalProvider{ + "random": { + VersionConstraint: "3.2.0", + Source: "hashicorp/random", + }, + } +} + func providerVersion332() map[string]resource.ExternalProvider { return map[string]resource.ExternalProvider{ "random": { diff --git a/internal/provider/resource_password_test.go b/internal/provider/resource_password_test.go index 94235229..eefc8433 100644 --- a/internal/provider/resource_password_test.go +++ b/internal/provider/resource_password_test.go @@ -506,6 +506,163 @@ func TestAccResourcePassword_Min(t *testing.T) { }) } +// TestAccResourcePassword_UpgradeFromVersion2_2_1 requires that you are running an amd64 Terraform binary +// if you are running this test locally on arm64 architecture otherwise you will see the following error: +// Error: Incompatible provider version +// +// Provider registry.terraform.io/hashicorp/random v2.2.1 does not have a +// package available for your current platform ... +// +// TestAccResourcePassword_UpgradeFromVersion2_2_1 verifies behaviour when upgrading state from schema V0 to V2. +func TestAccResourcePassword_UpgradeFromVersion2_2_1(t *testing.T) { + resource.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + ExternalProviders: providerVersion221(), + Config: `resource "random_password" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrWith("random_password.min", "result", testCheckLen(12)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([a-z].*){2,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([0-9].*){4,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([!#@])`)), + resource.TestCheckResourceAttr("random_password.min", "special", "true"), + resource.TestCheckResourceAttr("random_password.min", "upper", "true"), + resource.TestCheckResourceAttr("random_password.min", "lower", "true"), + resource.TestCheckResourceAttr("random_password.min", "number", "true"), + resource.TestCheckResourceAttr("random_password.min", "min_special", "1"), + resource.TestCheckResourceAttr("random_password.min", "min_upper", "3"), + resource.TestCheckResourceAttr("random_password.min", "min_lower", "2"), + resource.TestCheckResourceAttr("random_password.min", "min_numeric", "4"), + ), + }, + { + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Config: `resource "random_password" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + PlanOnly: true, + }, + { + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Config: `resource "random_password" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrWith("random_password.min", "result", testCheckLen(12)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([a-z].*){2,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([0-9].*){4,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([!#@])`)), + resource.TestCheckResourceAttr("random_password.min", "special", "true"), + resource.TestCheckResourceAttr("random_password.min", "upper", "true"), + resource.TestCheckResourceAttr("random_password.min", "lower", "true"), + resource.TestCheckResourceAttr("random_password.min", "number", "true"), + resource.TestCheckResourceAttr("random_password.min", "numeric", "true"), + resource.TestCheckResourceAttr("random_password.min", "min_special", "1"), + resource.TestCheckResourceAttr("random_password.min", "min_upper", "3"), + resource.TestCheckResourceAttr("random_password.min", "min_lower", "2"), + resource.TestCheckResourceAttr("random_password.min", "min_numeric", "4"), + resource.TestCheckResourceAttrSet("random_password.min", "bcrypt_hash"), + ), + }, + }, + }) +} + +// TestAccResourcePassword_UpgradeFromVersion3_2_0 verifies behaviour when upgrading state from schema V1 to V2. +func TestAccResourcePassword_UpgradeFromVersion3_2_0(t *testing.T) { + resource.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + ExternalProviders: providerVersion320(), + Config: `resource "random_password" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrWith("random_password.min", "result", testCheckLen(12)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([a-z].*){2,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([0-9].*){4,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([!#@])`)), + resource.TestCheckResourceAttr("random_password.min", "special", "true"), + resource.TestCheckResourceAttr("random_password.min", "upper", "true"), + resource.TestCheckResourceAttr("random_password.min", "lower", "true"), + resource.TestCheckResourceAttr("random_password.min", "number", "true"), + resource.TestCheckResourceAttr("random_password.min", "min_special", "1"), + resource.TestCheckResourceAttr("random_password.min", "min_upper", "3"), + resource.TestCheckResourceAttr("random_password.min", "min_lower", "2"), + resource.TestCheckResourceAttr("random_password.min", "min_numeric", "4"), + resource.TestCheckResourceAttrSet("random_password.min", "bcrypt_hash"), + ), + }, + { + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Config: `resource "random_password" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + PlanOnly: true, + }, + { + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Config: `resource "random_password" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrWith("random_password.min", "result", testCheckLen(12)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([a-z].*){2,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([0-9].*){4,}`)), + resource.TestMatchResourceAttr("random_password.min", "result", regexp.MustCompile(`([!#@])`)), + resource.TestCheckResourceAttr("random_password.min", "special", "true"), + resource.TestCheckResourceAttr("random_password.min", "upper", "true"), + resource.TestCheckResourceAttr("random_password.min", "lower", "true"), + resource.TestCheckResourceAttr("random_password.min", "number", "true"), + resource.TestCheckResourceAttr("random_password.min", "numeric", "true"), + resource.TestCheckResourceAttr("random_password.min", "min_special", "1"), + resource.TestCheckResourceAttr("random_password.min", "min_upper", "3"), + resource.TestCheckResourceAttr("random_password.min", "min_lower", "2"), + resource.TestCheckResourceAttr("random_password.min", "min_numeric", "4"), + resource.TestCheckResourceAttrSet("random_password.min", "bcrypt_hash"), + ), + }, + }, + }) +} + +// TestAccResourcePassword_UpgradeFromVersion3_3_2 verifies behaviour when upgrading from SDKv2 to the Framework. func TestAccResourcePassword_UpgradeFromVersion3_3_2(t *testing.T) { resource.Test(t, resource.TestCase{ Steps: []resource.TestStep{ diff --git a/internal/provider/resource_string_test.go b/internal/provider/resource_string_test.go index a6b737d2..ec39fe55 100644 --- a/internal/provider/resource_string_test.go +++ b/internal/provider/resource_string_test.go @@ -300,6 +300,80 @@ func TestAccResourceString_LengthErrors(t *testing.T) { }) } +// TestAccResourceString_UpgradeFromVersion3_2_0 verifies behaviour when upgrading state from schema V1 to V2. +func TestAccResourceString_UpgradeFromVersion3_2_0(t *testing.T) { + resource.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + ExternalProviders: providerVersion320(), + Config: `resource "random_string" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrWith("random_string.min", "result", testCheckLen(12)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([a-z].*){2,}`)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([0-9].*){4,}`)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([!#@])`)), + resource.TestCheckResourceAttr("random_string.min", "special", "true"), + resource.TestCheckResourceAttr("random_string.min", "upper", "true"), + resource.TestCheckResourceAttr("random_string.min", "lower", "true"), + resource.TestCheckResourceAttr("random_string.min", "number", "true"), + resource.TestCheckResourceAttr("random_string.min", "min_special", "1"), + resource.TestCheckResourceAttr("random_string.min", "min_upper", "3"), + resource.TestCheckResourceAttr("random_string.min", "min_lower", "2"), + resource.TestCheckResourceAttr("random_string.min", "min_numeric", "4"), + ), + }, + { + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Config: `resource "random_string" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + PlanOnly: true, + }, + { + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Config: `resource "random_string" "min" { + length = 12 + override_special = "!#@" + min_lower = 2 + min_upper = 3 + min_special = 1 + min_numeric = 4 + }`, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrWith("random_string.min", "result", testCheckLen(12)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([a-z].*){2,}`)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([0-9].*){4,}`)), + resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([!#@])`)), + resource.TestCheckResourceAttr("random_string.min", "special", "true"), + resource.TestCheckResourceAttr("random_string.min", "upper", "true"), + resource.TestCheckResourceAttr("random_string.min", "lower", "true"), + resource.TestCheckResourceAttr("random_string.min", "number", "true"), + resource.TestCheckResourceAttr("random_string.min", "numeric", "true"), + resource.TestCheckResourceAttr("random_string.min", "min_special", "1"), + resource.TestCheckResourceAttr("random_string.min", "min_upper", "3"), + resource.TestCheckResourceAttr("random_string.min", "min_lower", "2"), + resource.TestCheckResourceAttr("random_string.min", "min_numeric", "4"), + ), + }, + }, + }) +} + +// TestAccResourceString_UpgradeFromVersion3_3_2 verifies behaviour when upgrading from SDKv2 to the Framework. func TestAccResourceString_UpgradeFromVersion3_3_2(t *testing.T) { resource.Test(t, resource.TestCase{ Steps: []resource.TestStep{ From 8dc076952d75f4c8153ff55a82d44c6a59360512 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Aug 2022 22:04:58 +0100 Subject: [PATCH 4/6] Linting (#302) --- internal/provider/resource_password_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/provider/resource_password_test.go b/internal/provider/resource_password_test.go index eefc8433..46352ab7 100644 --- a/internal/provider/resource_password_test.go +++ b/internal/provider/resource_password_test.go @@ -508,10 +508,11 @@ func TestAccResourcePassword_Min(t *testing.T) { // TestAccResourcePassword_UpgradeFromVersion2_2_1 requires that you are running an amd64 Terraform binary // if you are running this test locally on arm64 architecture otherwise you will see the following error: -// Error: Incompatible provider version // -// Provider registry.terraform.io/hashicorp/random v2.2.1 does not have a -// package available for your current platform ... +// Error: Incompatible provider version +// +// Provider registry.terraform.io/hashicorp/random v2.2.1 does not have a +// package available for your current platform ... // // TestAccResourcePassword_UpgradeFromVersion2_2_1 verifies behaviour when upgrading state from schema V0 to V2. func TestAccResourcePassword_UpgradeFromVersion2_2_1(t *testing.T) { From 7bb1edb7f3191a519e4eb004ec8b5f79e013b49c Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 1 Sep 2022 11:18:52 +0100 Subject: [PATCH 5/6] Amend CHANGELOG (#302) --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcd64245..e407c882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ BUG FIXES: -* resource/random_password: During upgrade state, ensure `min_upper` is populated ([302](https://github.com/hashicorp/terraform-provider-random/pull/302)). -* resource/random_string: During upgrade state, ensure `min_upper` is populated ([302](https://github.com/hashicorp/terraform-provider-random/pull/302)). +* resource/random_password: During upgrade state, ensure `min_upper` is populated ([304](https://github.com/hashicorp/terraform-provider-random/pull/304)). +* resource/random_string: During upgrade state, ensure `min_upper` is populated ([304](https://github.com/hashicorp/terraform-provider-random/pull/304)). ## 3.4.1 (August 31, 2022) From 5b5e6b816c3ab2ced930017f790b7ada88cd4c30 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Fri, 2 Sep 2022 09:14:38 +0100 Subject: [PATCH 6/6] Skip test on darwin/arm64 as binary not available for random provider v2.2.1 (#302) --- internal/provider/resource_password_test.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/provider/resource_password_test.go b/internal/provider/resource_password_test.go index 46352ab7..2445c963 100644 --- a/internal/provider/resource_password_test.go +++ b/internal/provider/resource_password_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "regexp" + "runtime" "testing" "github.com/google/go-cmp/cmp" @@ -506,17 +507,14 @@ func TestAccResourcePassword_Min(t *testing.T) { }) } -// TestAccResourcePassword_UpgradeFromVersion2_2_1 requires that you are running an amd64 Terraform binary -// if you are running this test locally on arm64 architecture otherwise you will see the following error: -// -// Error: Incompatible provider version -// -// Provider registry.terraform.io/hashicorp/random v2.2.1 does not have a -// package available for your current platform ... -// // TestAccResourcePassword_UpgradeFromVersion2_2_1 verifies behaviour when upgrading state from schema V0 to V2. func TestAccResourcePassword_UpgradeFromVersion2_2_1(t *testing.T) { resource.Test(t, resource.TestCase{ + PreCheck: func() { + if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" { + t.Skip("This test requires darwin/amd64 to download the old provider version. Setting TF_ACC_TERRAFORM_PATH to darwin/amd64 compatible Terraform binary can be used as a workaround.") + } + }, Steps: []resource.TestStep{ { ExternalProviders: providerVersion221(),