Skip to content
3 changes: 3 additions & 0 deletions .changelog/43516.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
provider: Prevent planned `forces replacement` on `region` when upgrading from a pre-v6.0.0 provider version and `-refresh=false` is in effect
```
18 changes: 15 additions & 3 deletions internal/provider/framework/region.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ func (r resourceForceNewIfRegionChangesInterceptor) modifyPlan(ctx context.Conte
return diags
}

var configRegion types.String
diags.Append(request.Config.GetAttribute(ctx, path.Root(names.AttrRegion), &configRegion)...)
if diags.HasError() {
return diags
}

var planRegion types.String
diags.Append(request.Plan.GetAttribute(ctx, path.Root(names.AttrRegion), &planRegion)...)
if diags.HasError() {
Expand All @@ -292,9 +298,15 @@ func (r resourceForceNewIfRegionChangesInterceptor) modifyPlan(ctx context.Conte
return diags
}

providerRegion := c.AwsConfig(ctx).Region
if stateRegion.IsNull() && planRegion.ValueString() == providerRegion {
return diags
if stateRegion.IsNull() {
// Upgrade from pre-v6.0.0 provider and '-refresh=false' in effect.
if configRegion.IsNull() {
return diags
}

if providerRegion := c.AwsConfig(ctx).Region; planRegion.ValueString() == providerRegion {
return diags
}
}

if !planRegion.Equal(stateRegion) {
Expand Down
260 changes: 260 additions & 0 deletions internal/service/appfabric/app_bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,256 @@ func testAccAppBundle_upgradeFromV5(t *testing.T) {
})
}

func testAccAppBundle_upgradeFromV5PlanRefreshFalse(t *testing.T) {
ctx := acctest.Context(t)
var appbundle awstypes.AppBundle
resourceName := "aws_appfabric_app_bundle.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckRegion(t, endpoints.UsEast1RegionID, endpoints.ApNortheast1RegionID, endpoints.EuWest1RegionID)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.AppFabricServiceID),
CheckDestroy: testAccCheckAppBundleDestroy(ctx),
AdditionalCLIOptions: &resource.AdditionalCLIOptions{
Plan: resource.PlanOptions{
NoRefresh: true,
},
},
Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
"aws": {
Source: "hashicorp/aws",
VersionConstraint: "5.100.0",
},
},
Config: testAccAppBundleConfig_basic,
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExists(ctx, resourceName, &appbundle),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
},
},
ConfigStateChecks: []statecheck.StateCheck{
tfstatecheck.ExpectNoValue(resourceName, tfjsonpath.New(names.AttrRegion)),
},
},
{
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Config: testAccAppBundleConfig_basic,
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExists(ctx, resourceName, &appbundle),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate),
},
PostApplyPostRefresh: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop),
},
},
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())),
},
},
},
})
}

func testAccAppBundle_upgradeFromV5WithUpdatePlanRefreshFalse(t *testing.T) {
ctx := acctest.Context(t)
var appbundle awstypes.AppBundle
resourceName := "aws_appfabric_app_bundle.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckRegion(t, endpoints.UsEast1RegionID, endpoints.ApNortheast1RegionID, endpoints.EuWest1RegionID)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.AppFabricServiceID),
CheckDestroy: testAccCheckAppBundleDestroy(ctx),
AdditionalCLIOptions: &resource.AdditionalCLIOptions{
Plan: resource.PlanOptions{
NoRefresh: true,
},
},
Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
"aws": {
Source: "hashicorp/aws",
VersionConstraint: "5.100.0",
},
},
Config: testAccAppBundleConfig_tags1(acctest.CtKey1, acctest.CtValue1),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExists(ctx, resourceName, &appbundle),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
},
},
ConfigStateChecks: []statecheck.StateCheck{
tfstatecheck.ExpectNoValue(resourceName, tfjsonpath.New(names.AttrRegion)),
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{
acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1),
})),
},
},
{
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Config: testAccAppBundleConfig_tags1(acctest.CtKey1, acctest.CtValue1Updated),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExists(ctx, resourceName, &appbundle),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate),
},
PostApplyPostRefresh: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop),
},
},
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())),
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{
acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1Updated),
})),
},
},
},
})
}

func testAccAppBundle_upgradeFromV5WithDefaultRegionRefreshFalse(t *testing.T) {
ctx := acctest.Context(t)
var appbundle awstypes.AppBundle
resourceName := "aws_appfabric_app_bundle.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckRegion(t, endpoints.UsEast1RegionID, endpoints.ApNortheast1RegionID, endpoints.EuWest1RegionID)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.AppFabricServiceID),
CheckDestroy: testAccCheckAppBundleDestroy(ctx),
AdditionalCLIOptions: &resource.AdditionalCLIOptions{
Plan: resource.PlanOptions{
NoRefresh: true,
},
},
Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
"aws": {
Source: "hashicorp/aws",
VersionConstraint: "5.100.0",
},
},
Config: testAccAppBundleConfig_basic,
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExists(ctx, resourceName, &appbundle),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
},
},
ConfigStateChecks: []statecheck.StateCheck{
tfstatecheck.ExpectNoValue(resourceName, tfjsonpath.New(names.AttrRegion)),
},
},
{
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Config: testAccAppBundleConfig_region(acctest.Region()),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExists(ctx, resourceName, &appbundle),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate),
},
PostApplyPostRefresh: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop),
},
},
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())),
},
},
},
})
}

func testAccAppBundle_upgradeFromV5WithNewRegionRefreshFalse(t *testing.T) {
ctx := acctest.Context(t)
var appbundle awstypes.AppBundle
resourceName := "aws_appfabric_app_bundle.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckRegion(t, endpoints.UsEast1RegionID)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.AppFabricServiceID),
CheckDestroy: testAccCheckAppBundleDestroy(ctx),
AdditionalCLIOptions: &resource.AdditionalCLIOptions{
Plan: resource.PlanOptions{
NoRefresh: true,
},
},
Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
"aws": {
Source: "hashicorp/aws",
VersionConstraint: "5.100.0",
},
},
Config: testAccAppBundleConfig_basic,
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExists(ctx, resourceName, &appbundle),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
},
},
ConfigStateChecks: []statecheck.StateCheck{
tfstatecheck.ExpectNoValue(resourceName, tfjsonpath.New(names.AttrRegion)),
},
},
{
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Config: testAccAppBundleConfig_region(endpoints.EuWest1RegionID),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAppBundleExistsInRegion(ctx, resourceName, &appbundle, endpoints.EuWest1RegionID),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionReplace),
},
PostApplyPostRefresh: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop),
},
},
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(endpoints.EuWest1RegionID)),
},
},
},
})
}

func testAccAppBundle_regionCreateNull(t *testing.T) {
ctx := acctest.Context(t)
var appbundle awstypes.AppBundle
Expand Down Expand Up @@ -427,6 +677,16 @@ resource "aws_appfabric_app_bundle" "test" {
`, rName)
}

func testAccAppBundleConfig_tags1(tagKey1, tagValue1 string) string {
return fmt.Sprintf(`
resource "aws_appfabric_app_bundle" "test" {
tags = {
%[1]q = %[2]q
}
}
`, tagKey1, tagValue1)
}

func testAccAppBundleConfig_region(region string) string {
if region != "null" {
region = strconv.Quote(region)
Expand Down
20 changes: 12 additions & 8 deletions internal/service/appfabric/appfabric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ func TestAccAppFabric_serial(t *testing.T) {

testCases := map[string]map[string]func(t *testing.T){
"AppBundle": {
acctest.CtBasic: testAccAppBundle_basic,
acctest.CtDisappears: testAccAppBundle_disappears,
"cmk": testAccAppBundle_cmk,
"tags": testAccAppFabricAppBundle_tagsSerial,
"regionCreateNull": testAccAppBundle_regionCreateNull,
"regionCreateNonNull": testAccAppBundle_regionCreateNonNull,
"upgradeFromV5": testAccAppBundle_upgradeFromV5,
"Identity": testAccAppFabricAppBundle_IdentitySerial,
acctest.CtBasic: testAccAppBundle_basic,
acctest.CtDisappears: testAccAppBundle_disappears,
"cmk": testAccAppBundle_cmk,
"tags": testAccAppFabricAppBundle_tagsSerial,
"regionCreateNull": testAccAppBundle_regionCreateNull,
"regionCreateNonNull": testAccAppBundle_regionCreateNonNull,
"upgradeFromV5": testAccAppBundle_upgradeFromV5,
"upgradeFromV5PlanRefreshFalse": testAccAppBundle_upgradeFromV5PlanRefreshFalse,
"upgradeFromV5WithUpdatePlanRefreshFalse": testAccAppBundle_upgradeFromV5WithUpdatePlanRefreshFalse,
"upgradeFromV5WithDefaultRegionRefreshFalse": testAccAppBundle_upgradeFromV5WithDefaultRegionRefreshFalse,
"upgradeFromV5WithNewRegionRefreshFalse": testAccAppBundle_upgradeFromV5WithNewRegionRefreshFalse,
"Identity": testAccAppFabricAppBundle_IdentitySerial,
},
"AppAuthorization": {
acctest.CtBasic: testAccAppAuthorization_basic,
Expand Down
Loading
Loading