Skip to content

Commit

Permalink
add upgrade tests to detect breaking changes (#474)
Browse files Browse the repository at this point in the history
* add upgrade tests to detect breaking changes

* add more tests
  • Loading branch information
ms-henglu committed Apr 26, 2024
1 parent bc38e6b commit fedc710
Show file tree
Hide file tree
Showing 14 changed files with 905 additions and 49 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ BUG FIXES:
- Fix a bug that schema validation fails to validate the float number in the body.
- Fix a bug that client certificate authentication doesn't work.
- Fix a bug that auxiliary tenant ids are not passed to the client.
- Fix a bug that `azapi_resource_action` resource shows the plan diff when upgrading from the previous provider.

## v1.13.0
BREAKING CHANGES:
Expand Down
19 changes: 19 additions & 0 deletions internal/acceptance/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ func (td TestData) ImportStep(ignore ...string) resource.TestStep {
return td.ImportStepFor(td.ResourceName, ignore...)
}

// ImportStep returns a Test Step which Imports the Resource, optionally
// ignoring any fields which may not be imported (for example, as they're
// not returned from the API)
func (td TestData) ImportStepWithImportStateIdFunc(importStateIdFunc resource.ImportStateIdFunc, ignore ...string) resource.TestStep {
resourceName := td.ResourceName
step := resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: importStateIdFunc,
}

if len(ignore) > 0 {
step.ImportStateVerifyIgnore = ignore
}

return step
}

// ImportStepFor returns a Test Step which Imports a given resource by name,
// optionally ignoring any fields which may not be imported (for example, as they're
// not returned from the API)
Expand Down
34 changes: 34 additions & 0 deletions internal/acceptance/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,40 @@ func (td *TestData) RandomStringOfLength(len int) string {
return acctest.RandStringFromCharSet(len, charSetAlphaNum)
}

// UpgradeTestDeployStep returns a test step used to deploy the configuration with previous version
func (td TestData) UpgradeTestDeployStep(step resource.TestStep, upgradeFrom string) resource.TestStep {
step.ExternalProviders = td.externalProviders()
step.ExternalProviders["azapi"] = resource.ExternalProvider{
Source: "registry.terraform.io/azure/azapi",
VersionConstraint: fmt.Sprintf("= %s", upgradeFrom),
}
step.ProtoV6ProviderFactories = nil
return step
}

// UpgradeTestPlanStep returns a test step used to run terraform plan with the development version to check if there's any changes
func (td TestData) UpgradeTestPlanStep(planStep resource.TestStep) resource.TestStep {
planStep.PlanOnly = true
planStep.ExternalProviders = td.externalProviders()
planStep.ProtoV6ProviderFactories = td.providers()
return planStep
}

func (td TestData) UpgradeTest(t *testing.T, testResource TestResource, steps []resource.TestStep) {
testCase := resource.TestCase{
PreCheck: func() { PreCheck(t) },
CheckDestroy: func(s *terraform.State) error {
client, err := BuildTestClient()
if err != nil {
return fmt.Errorf("building client: %+v", err)
}
return CheckDestroyedFunc(client, testResource, td.ResourceType, td.ResourceName)(s)
},
Steps: steps,
}
resource.ParallelTest(t, testCase)
}

// lintignore:AT001
func (td TestData) DataSourceTest(t *testing.T, steps []resource.TestStep) {
// DataSources don't need a check destroy - however since this is a wrapper function
Expand Down
1 change: 1 addition & 0 deletions internal/services/azapi_data_plane_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ resource "azurerm_app_configuration" "appconf" {
name = "acctest%[2]s"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
sku = "standard"
}
data "azurerm_client_config" "current" {}
Expand Down
94 changes: 94 additions & 0 deletions internal/services/azapi_data_plane_resource_upgrade_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package services_test

import (
"testing"

"github.com/Azure/terraform-provider-azapi/internal/acceptance"
"github.com/Azure/terraform-provider-azapi/internal/acceptance/check"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccAzapiDataPlaneResourceUpgrade_appConfigKeyValues(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_data_plane_resource", "test")
r := DataPlaneResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.appConfigKeyValues(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.appConfigKeyValues(data),
}),
})
}

func TestAccAzapiDataPlaneResourceUpgrade_purviewClassification(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_data_plane_resource", "test")
r := DataPlaneResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.purviewClassification(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.purviewClassification(data),
}),
})
}

func TestAccAzapiDataPlaneResourceUpgrade_purviewCollection(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_data_plane_resource", "test")
r := DataPlaneResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.purviewCollection(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.purviewCollection(data),
}),
})
}

func TestAccAzapiDataPlaneResourceUpgrade_keyVaultIssuer(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_data_plane_resource", "test")
r := DataPlaneResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.keyVaultIssuer(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.keyVaultIssuer(data),
}),
})
}

func TestAccAzapiDataPlaneResourceUpgrade_iotAppsUser(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_data_plane_resource", "test")
r := DataPlaneResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.iotAppsUser(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.iotAppsUser(data),
}),
})
}
6 changes: 5 additions & 1 deletion internal/services/azapi_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,10 @@ func (r *AzapiResource) locationWithDefaultLocation(config types.String, body ma
return state.Location
}
}
// To suppress the diff of config: location = null and state: location = ""
// This case happens when upgrading resources which doesn't support location from terraform-plugin-sdk built azapi provider
case state != nil && !state.Location.IsUnknown() && state.Location.ValueString() == "":
return state.Location
}
}
return config
Expand All @@ -906,7 +910,7 @@ func expandBody(body map[string]interface{}, model AzapiResourceModel) diag.Diag
if body == nil {
return diag.Diagnostics{}
}
if body["location"] == nil && !model.Location.IsNull() && !model.Location.IsUnknown() {
if body["location"] == nil && !model.Location.IsNull() && !model.Location.IsUnknown() && len(model.Location.ValueString()) != 0 {
body["location"] = model.Location.ValueString()
}
if body["tags"] == nil && !model.Tags.IsNull() && !model.Tags.IsUnknown() && len(model.Tags.Elements()) != 0 {
Expand Down
11 changes: 9 additions & 2 deletions internal/services/azapi_resource_action_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,6 @@ func (r *ActionResource) Schema(ctx context.Context, request resource.SchemaRequ
// TODO: Remove the support for JSON string in the next major release
"body": schema.DynamicAttribute{
Optional: true,
Computed: true,
Default: defaults.DynamicDefault(types.StringValue("{}")),
Validators: []validator.Dynamic{
myvalidator.BodyValidator(),
},
Expand Down Expand Up @@ -238,7 +236,16 @@ func (r *ActionResource) Delete(ctx context.Context, request resource.DeleteRequ
}

func (r *ActionResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
var state ActionResourceModel
if response.Diagnostics.Append(request.State.Get(ctx, &state)...); response.Diagnostics.HasError() {
return
}

if state.When.IsNull() {
state.When = basetypes.NewStringValue("apply")
}

response.Diagnostics.Append(response.State.Set(ctx, state)...)
}

func (r *ActionResource) Action(ctx context.Context, model ActionResourceModel, state *tfsdk.State, diagnostics *diag.Diagnostics) {
Expand Down
18 changes: 11 additions & 7 deletions internal/services/azapi_resource_action_resource_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
package services_test

import (
"context"
"fmt"
"testing"

"github.com/Azure/terraform-provider-azapi/internal/acceptance"
"github.com/Azure/terraform-provider-azapi/internal/clients"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

type ActionResource struct{}

func (r ActionResource) Exists(ctx context.Context, client *clients.Client, state *terraform.InstanceState) (*bool, error) {
out := false
return &out, nil
}

func TestAccActionResource_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_resource_action", "test")
r := ActionResource{}
Expand Down Expand Up @@ -109,7 +117,7 @@ resource "azapi_resource_action" "test" {
data.azapi_resource_action.list
]
}
`, GenericResource{}.defaultTag(data))
`, GenericResource{}.identityNone(data))
}

func (r ActionResource) basicWhenDestroy(data acceptance.TestData) string {
Expand All @@ -136,7 +144,7 @@ resource "azapi_resource_action" "test" {
]
response_export_values = ["*"]
}
`, GenericResource{}.defaultTag(data))
`, GenericResource{}.identityNone(data))
}

func (r ActionResource) registerResourceProvider() string {
Expand Down Expand Up @@ -262,9 +270,5 @@ resource "azapi_resource_action" "test" {
}
})
}
`, data.LocationPrimary, data.RandomStringOfLength(10))
`, data.LocationPrimary, data.RandomString)
}
98 changes: 98 additions & 0 deletions internal/services/azapi_resource_action_resource_upgrade_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package services_test

import (
"testing"

"github.com/Azure/terraform-provider-azapi/internal/acceptance"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccAzapiActionResourceUpgrade_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_resource_action", "test")
r := ActionResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.basic(data),
}),
})
}

func TestAccAzapiActionResourceUpgrade_basicWhenDestroy(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_resource_action", "test")
r := ActionResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.basicWhenDestroy(data),
Check: resource.ComposeTestCheckFunc(),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.basicWhenDestroy(data),
}),
})
}

func TestAccAzapiActionResourceUpgrade_registerResourceProvider(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_resource_action", "test")
r := ActionResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.registerResourceProvider(),
Check: resource.ComposeTestCheckFunc(),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.registerResourceProvider(),
}),
})
}

func TestAccAzapiActionResourceUpgrade_upgradeFromVeryOldVersion(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_resource_action", "test")
r := ActionResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.registerResourceProvider(),
Check: resource.ComposeTestCheckFunc(),
}, "1.8.0"),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.registerResourceProvider(),
}),
})
}

func TestAccAzapiActionResourceUpgrade_providerAction(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_resource_action", "test")
r := ActionResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.providerAction(),
Check: resource.ComposeTestCheckFunc(),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.providerAction(),
}),
})
}

func TestAccAzapiActionResourceUpgrade_nonstandardLRO(t *testing.T) {
data := acceptance.BuildTestData(t, "azapi_resource_action", "test")
r := ActionResource{}

data.UpgradeTest(t, r, []resource.TestStep{
data.UpgradeTestDeployStep(resource.TestStep{
Config: r.nonstandardLRO(data),
Check: resource.ComposeTestCheckFunc(),
}, PreviousVersion),
data.UpgradeTestPlanStep(resource.TestStep{
Config: r.nonstandardLRO(data),
}),
})
}

0 comments on commit fedc710

Please sign in to comment.