Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion internal/services/storagemover/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,7 @@ func (r Registration) EphemeralResources() []func() ephemeral.EphemeralResource
}

func (r Registration) ListResources() []sdk.FrameworkListWrappedResource {
return []sdk.FrameworkListWrappedResource{}
return []sdk.FrameworkListWrappedResource{
StorageMoverProjectListResource{},
}
}
45 changes: 33 additions & 12 deletions internal/services/storagemover/storage_mover_project_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ import (

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
"github.com/hashicorp/go-azure-sdk/resource-manager/storagemover/2025-07-01/projects"
"github.com/hashicorp/go-azure-sdk/resource-manager/storagemover/2025-07-01/storagemovers"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

//go:generate go run ../../tools/generator-tests resourceidentity -resource-name storage_mover_project -service-package-name storagemover -properties "name" -compare-values "subscription_id:storage_mover_id,resource_group_name:storage_mover_id,storage_mover_name:storage_mover_id"

type StorageMoverProjectResourceModel struct {
Name string `tfschema:"name"`
StorageMoverId string `tfschema:"storage_mover_id"`
Expand All @@ -26,7 +29,14 @@ type StorageMoverProjectResourceModel struct {

type StorageMoverProjectResource struct{}

var _ sdk.ResourceWithUpdate = StorageMoverProjectResource{}
var (
_ sdk.ResourceWithIdentity = StorageMoverProjectResource{}
_ sdk.ResourceWithUpdate = StorageMoverProjectResource{}
)

func (r StorageMoverProjectResource) Identity() resourceids.ResourceId {
return &projects.ProjectId{}
}

func (r StorageMoverProjectResource) ResourceType() string {
return "azurerm_storage_mover_project"
Expand Down Expand Up @@ -109,6 +119,9 @@ func (r StorageMoverProjectResource) Create() sdk.ResourceFunc {
}

metadata.SetID(id)
if err := pluginsdk.SetResourceIdentityData(metadata.ResourceData, &id); err != nil {
return err
}
return nil
},
}
Expand Down Expand Up @@ -173,20 +186,28 @@ func (r StorageMoverProjectResource) Read() sdk.ResourceFunc {
return fmt.Errorf("retrieving %s: %+v", *id, err)
}

state := StorageMoverProjectResourceModel{
Name: id.ProjectName,
StorageMoverId: storagemovers.NewStorageMoverID(id.SubscriptionId, id.ResourceGroupName, id.StorageMoverName).ID(),
}
return r.flatten(metadata, id, resp.Model)
},
}
}

if resp.Model != nil {
if properties := resp.Model.Properties; properties != nil {
state.Description = pointer.From(properties.Description)
}
}
func (r StorageMoverProjectResource) flatten(metadata sdk.ResourceMetaData, id *projects.ProjectId, model *projects.Project) error {
state := StorageMoverProjectResourceModel{
Name: id.ProjectName,
StorageMoverId: storagemovers.NewStorageMoverID(id.SubscriptionId, id.ResourceGroupName, id.StorageMoverName).ID(),
}

return metadata.Encode(&state)
},
if model != nil {
if properties := model.Properties; properties != nil {
state.Description = pointer.From(properties.Description)
}
}

if err := pluginsdk.SetResourceIdentityData(metadata.ResourceData, id); err != nil {
return err
}

return metadata.Encode(&state)
}

func (r StorageMoverProjectResource) Delete() sdk.ResourceFunc {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright IBM Corp. 2014, 2025
// SPDX-License-Identifier: MPL-2.0

package storagemover_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
customstatecheck "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/statecheck"
)

func TestAccStorageMoverProject_resourceIdentity(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_mover_project", "test")
r := StorageMoverProjectResource{}

checkedFields := map[string]struct{}{
"name": {},
"resource_group_name": {},
"storage_mover_name": {},
"subscription_id": {},
}

data.ResourceIdentityTest(t, []acceptance.TestStep{
{
Config: r.basic(data),
ConfigStateChecks: []statecheck.StateCheck{
customstatecheck.ExpectAllIdentityFieldsAreChecked("azurerm_storage_mover_project.test", checkedFields),
statecheck.ExpectIdentityValueMatchesStateAtPath("azurerm_storage_mover_project.test", tfjsonpath.New("name"), tfjsonpath.New("name")),
customstatecheck.ExpectStateContainsIdentityValueAtPath("azurerm_storage_mover_project.test", tfjsonpath.New("resource_group_name"), tfjsonpath.New("storage_mover_id")),
customstatecheck.ExpectStateContainsIdentityValueAtPath("azurerm_storage_mover_project.test", tfjsonpath.New("storage_mover_name"), tfjsonpath.New("storage_mover_id")),
customstatecheck.ExpectStateContainsIdentityValueAtPath("azurerm_storage_mover_project.test", tfjsonpath.New("subscription_id"), tfjsonpath.New("storage_mover_id")),
},
},
data.ImportBlockWithResourceIdentityStep(false),
data.ImportBlockWithIDStep(false),
}, false)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: MPL-2.0

package storagemover

import (
"context"
"fmt"

"github.com/hashicorp/go-azure-helpers/framework/typehelpers"
"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-sdk/resource-manager/storagemover/2025-07-01/projects"
"github.com/hashicorp/go-azure-sdk/resource-manager/storagemover/2025-07-01/storagemovers"
"github.com/hashicorp/terraform-plugin-framework/list"
"github.com/hashicorp/terraform-plugin-framework/list/schema"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

type StorageMoverProjectListResource struct{}

type StorageMoverProjectListModel struct {
StorageMoverId types.String `tfsdk:"storage_mover_id"`
}

var _ sdk.FrameworkListWrappedResource = new(StorageMoverProjectListResource)

func (StorageMoverProjectListResource) Metadata(_ context.Context, _ resource.MetadataRequest, response *resource.MetadataResponse) {
response.TypeName = StorageMoverProjectResource{}.ResourceType()
}

func (StorageMoverProjectListResource) ResourceFunc() *pluginsdk.Resource {
return sdk.WrappedResource(StorageMoverProjectResource{})
}

func (StorageMoverProjectListResource) ListResourceConfigSchema(_ context.Context, _ list.ListResourceSchemaRequest, response *list.ListResourceSchemaResponse) {
response.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"storage_mover_id": schema.StringAttribute{
Required: true,
Validators: []validator.String{
typehelpers.WrappedStringValidator{Func: storagemovers.ValidateStorageMoverID},
},
},
},
}
}

func (StorageMoverProjectListResource) List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream, metadata sdk.ResourceMetadata) {
client := metadata.Client.StorageMover.ProjectsClient

var data StorageMoverProjectListModel
diags := request.Config.Get(ctx, &data)
if diags.HasError() {
stream.Results = list.ListResultsStreamDiagnostics(diags)
return
}

storageMoverID, err := storagemovers.ParseStorageMoverID(data.StorageMoverId.ValueString())
if err != nil {
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("parsing Storage Mover ID for `%s`", StorageMoverProjectResource{}.ResourceType()), err)
return
}

resp, err := client.ListComplete(ctx, projects.NewStorageMoverID(storageMoverID.SubscriptionId, storageMoverID.ResourceGroupName, storageMoverID.StorageMoverName))
if err != nil {
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("listing `%s`", StorageMoverProjectResource{}.ResourceType()), err)
return
}

resource := StorageMoverProjectResource{}
stream.Results = func(push func(list.ListResult) bool) {
for _, item := range resp.Items {
result := request.NewListResult(ctx)
result.DisplayName = pointer.From(item.Name)

id, err := projects.ParseProjectIDInsensitively(pointer.From(item.Id))
if err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "parsing Storage Mover Project ID", err)
return
}

meta := sdk.NewResourceMetaData(metadata.Client, resource)
meta.SetID(id)

if err := resource.flatten(meta, id, &item); err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, fmt.Sprintf("encoding `%s` resource data", resource.ResourceType()), err)
return
}

sdk.EncodeListResult(ctx, meta.ResourceData, &result)
if result.Diagnostics.HasError() {
push(result)
return
}

if !push(result) {
return
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: MPL-2.0

package storagemover_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/querycheck"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/provider/framework"
)

func TestAccStorageMoverProject_list(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_mover_project", "testlist")
r := StorageMoverProjectResource{}
resourceName := fmt.Sprintf("acctest-sp-%d", data.RandomInteger)
storageMoverName := fmt.Sprintf("acctest-ssm-%d", data.RandomInteger)
resourceGroupName := fmt.Sprintf("acctest-rg-%d", data.RandomInteger)

resource.Test(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_14_0),
},
ProtoV5ProviderFactories: framework.ProtoV5ProviderFactoriesInit(context.Background(), "azurerm"),
Steps: []resource.TestStep{
{Config: r.basic(data)},
{
Query: true,
Config: r.listQuery(),
QueryResultChecks: []querycheck.QueryResultCheck{
querycheck.ExpectLength("azurerm_storage_mover_project.list", 1),
querycheck.ExpectIdentity("azurerm_storage_mover_project.list", map[string]knownvalue.Check{
"name": knownvalue.StringExact(resourceName),
"resource_group_name": knownvalue.StringExact(resourceGroupName),
"storage_mover_name": knownvalue.StringExact(storageMoverName),
"subscription_id": knownvalue.StringExact(data.Subscriptions.Primary),
}),
},
},
},
})
}

func (r StorageMoverProjectResource) listQuery() string {
return `
list "azurerm_storage_mover_project" "list" {
provider = azurerm
config {
storage_mover_id = azurerm_storage_mover.test.id
}
}
`
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

type StorageMoverProjectTestResource struct{}
type StorageMoverProjectResource struct{}

func TestAccStorageMoverProject_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_mover_project", "test")
r := StorageMoverProjectTestResource{}
r := StorageMoverProjectResource{}
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Expand All @@ -35,7 +35,7 @@ func TestAccStorageMoverProject_basic(t *testing.T) {

func TestAccStorageMoverProject_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_mover_project", "test")
r := StorageMoverProjectTestResource{}
r := StorageMoverProjectResource{}
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Expand All @@ -49,7 +49,7 @@ func TestAccStorageMoverProject_requiresImport(t *testing.T) {

func TestAccStorageMoverProject_complete(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_mover_project", "test")
r := StorageMoverProjectTestResource{}
r := StorageMoverProjectResource{}
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.complete(data),
Expand All @@ -63,7 +63,7 @@ func TestAccStorageMoverProject_complete(t *testing.T) {

func TestAccStorageMoverProject_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_mover_project", "test")
r := StorageMoverProjectTestResource{}
r := StorageMoverProjectResource{}
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.complete(data),
Expand All @@ -82,7 +82,7 @@ func TestAccStorageMoverProject_update(t *testing.T) {
})
}

func (r StorageMoverProjectTestResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
func (r StorageMoverProjectResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := projects.ParseProjectID(state.ID)
if err != nil {
return nil, err
Expand All @@ -99,7 +99,7 @@ func (r StorageMoverProjectTestResource) Exists(ctx context.Context, clients *cl
return pointer.To(resp.Model != nil), nil
}

func (r StorageMoverProjectTestResource) template(data acceptance.TestData) string {
func (r StorageMoverProjectResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctest-rg-%d"
Expand All @@ -114,7 +114,7 @@ resource "azurerm_storage_mover" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (r StorageMoverProjectTestResource) basic(data acceptance.TestData) string {
func (r StorageMoverProjectResource) basic(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
provider "azurerm" {
Expand All @@ -130,7 +130,7 @@ resource "azurerm_storage_mover_project" "test" {
`, template, data.RandomInteger)
}

func (r StorageMoverProjectTestResource) requiresImport(data acceptance.TestData) string {
func (r StorageMoverProjectResource) requiresImport(data acceptance.TestData) string {
config := r.basic(data)
return fmt.Sprintf(`
%s
Expand All @@ -142,7 +142,7 @@ resource "azurerm_storage_mover_project" "import" {
`, config)
}

func (r StorageMoverProjectTestResource) complete(data acceptance.TestData) string {
func (r StorageMoverProjectResource) complete(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
provider "azurerm" {
Expand All @@ -159,7 +159,7 @@ resource "azurerm_storage_mover_project" "test" {
`, template, data.RandomInteger)
}

func (r StorageMoverProjectTestResource) update(data acceptance.TestData) string {
func (r StorageMoverProjectResource) update(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
Loading
Loading