Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions internal/services/storage/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func (r Registration) ListResources() []sdk.FrameworkListWrappedResource {
return []sdk.FrameworkListWrappedResource{
StorageAccountCustomerManagedKeyListResource{},
StorageAccountListResource{},
SyncServerEndpointListResource{},
Comment thread
aayushsingh2502 marked this conversation as resolved.
Outdated
StorageSyncListResource{},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ 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/storagesync/2020-03-01/registeredserverresource"
"github.com/hashicorp/go-azure-sdk/resource-manager/storagesync/2020-03-01/serverendpointresource"
"github.com/hashicorp/go-azure-sdk/sdk/client/pollers"
Expand All @@ -20,9 +21,14 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

//go:generate go run ../../tools/generator-tests resourceidentity -resource-name storage_sync_server_endpoint -service-package-name storage -properties "name" -compare-values "subscription_id:storage_sync_group_id,resource_group_name:storage_sync_group_id,storage_sync_service_name:storage_sync_group_id,sync_group_name:storage_sync_group_id" -test-sequential

type SyncServerEndpointResource struct{}

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

func (r SyncServerEndpointResource) ModelObject() interface{} {
return &StorageSyncServerEndpointResourceSchema{}
Expand All @@ -48,6 +54,10 @@ func (r SyncServerEndpointResource) ResourceType() string {
return "azurerm_storage_sync_server_endpoint"
}

func (r SyncServerEndpointResource) Identity() resourceids.ResourceId {
return &serverendpointresource.ServerEndpointId{}
}

func (r SyncServerEndpointResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"name": {
Expand Down Expand Up @@ -177,6 +187,9 @@ func (r SyncServerEndpointResource) Create() sdk.ResourceFunc {
}

metadata.SetID(id)
if err := pluginsdk.SetResourceIdentityData(metadata.ResourceData, &id); err != nil {
return err
}
return nil
},
}
Expand All @@ -188,8 +201,6 @@ func (r SyncServerEndpointResource) Read() sdk.ResourceFunc {
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Storage.SyncServerEndpointsClient

schema := StorageSyncServerEndpointResourceSchema{}

id, err := serverendpointresource.ParseServerEndpointID(metadata.ResourceData.Id())
if err != nil {
return err
Expand All @@ -203,25 +214,36 @@ func (r SyncServerEndpointResource) Read() sdk.ResourceFunc {
return fmt.Errorf("retrieving %s: %+v", *id, err)
}

if model := resp.Model; model != nil {
schema.Name = id.ServerEndpointName
if props := model.Properties; props != nil {
schema.StorageSyncGroupId = serverendpointresource.NewSyncGroupID(id.SubscriptionId, id.ResourceGroupName, id.StorageSyncServiceName, id.SyncGroupName).ID()
schema.RegisteredServerId = pointer.From(props.ServerResourceId)
schema.ServerLocalPath = pointer.From(props.ServerLocalPath)
schema.VolumeFreeSpacePercent = pointer.From(props.VolumeFreeSpacePercent)
schema.CloudTieringEnabled = pointer.From(props.CloudTiering) == serverendpointresource.FeatureStatusOn
schema.InitialDownloadPolicy = string(pointer.From(props.InitialDownloadPolicy))
schema.LocalCacheMode = string(pointer.From(props.LocalCacheMode))
if pointer.From(props.TierFilesOlderThanDays) != 0 {
schema.TierFilesOlderThanDays = pointer.From(props.TierFilesOlderThanDays)
}
}
return r.flatten(metadata, id, resp.Model)
},
}
}

func (r SyncServerEndpointResource) flatten(metadata sdk.ResourceMetaData, id *serverendpointresource.ServerEndpointId, model *serverendpointresource.ServerEndpoint) error {
schema := StorageSyncServerEndpointResourceSchema{
Name: id.ServerEndpointName,
StorageSyncGroupId: serverendpointresource.NewSyncGroupID(id.SubscriptionId, id.ResourceGroupName, id.StorageSyncServiceName, id.SyncGroupName).ID(),
}

if model != nil {
if props := model.Properties; props != nil {
schema.RegisteredServerId = pointer.From(props.ServerResourceId)
schema.ServerLocalPath = pointer.From(props.ServerLocalPath)
schema.VolumeFreeSpacePercent = pointer.From(props.VolumeFreeSpacePercent)
schema.CloudTieringEnabled = pointer.From(props.CloudTiering) == serverendpointresource.FeatureStatusOn
schema.InitialDownloadPolicy = string(pointer.From(props.InitialDownloadPolicy))
schema.LocalCacheMode = string(pointer.From(props.LocalCacheMode))
if pointer.From(props.TierFilesOlderThanDays) != 0 {
schema.TierFilesOlderThanDays = pointer.From(props.TierFilesOlderThanDays)
}
}
}

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

return metadata.Encode(&schema)
}

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

package storage_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 testAccStorageSyncServerEndpoint_resourceIdentity(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_sync_server_endpoint", "test")
r := StorageSyncServerEndpointResource{}

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

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

package storage

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/storagesync/2020-03-01/serverendpointresource"
"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 (
SyncServerEndpointListResource struct{}
SyncServerEndpointListModel struct {
StorageSyncGroupId types.String `tfsdk:"storage_sync_group_id"`
}
)

var _ sdk.FrameworkListWrappedResource = new(SyncServerEndpointListResource)

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

func (SyncServerEndpointListResource) ResourceFunc() *pluginsdk.Resource {
return sdk.WrappedResource(SyncServerEndpointResource{})
}

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

func (SyncServerEndpointListResource) List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream, metadata sdk.ResourceMetadata) {
client := metadata.Client.Storage.SyncServerEndpointsClient

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

syncGroupId, err := serverendpointresource.ParseSyncGroupID(data.StorageSyncGroupId.ValueString())
if err != nil {
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("parsing storage sync group id for `%s`", SyncServerEndpointResource{}.ResourceType()), err)
return
}

resp, err := client.ServerEndpointsListBySyncGroup(ctx, *syncGroupId)
if err != nil {
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("listing `%s`", SyncServerEndpointResource{}.ResourceType()), err)
return
}

results := make([]serverendpointresource.ServerEndpoint, 0)
if model := resp.Model; model != nil {
results = pointer.From(model.Value)
}

r := SyncServerEndpointResource{}

stream.Results = func(push func(list.ListResult) bool) {
for _, serverEndpoint := range results {
result := request.NewListResult(ctx)
result.DisplayName = pointer.From(serverEndpoint.Name)

id, err := serverendpointresource.ParseServerEndpointIDInsensitively(pointer.From(serverEndpoint.Id))
if err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "parsing Storage Sync Server Endpoint ID", err)
return
}

rmd := sdk.NewResourceMetaData(metadata.Client, r)
rmd.SetID(id)

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

sdk.EncodeListResult(ctx, rmd.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,54 @@
// Copyright IBM Corp. 2014, 2025
// SPDX-License-Identifier: MPL-2.0

package storage_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"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 TestAccStorageSyncServerEndpoint_list_basic(t *testing.T) {
t.Skip("@mbfrahry: temporarily skipping as the server must be registered manually. Will come back to this when the server can be registered programmatically")
Comment thread
aayushsingh2502 marked this conversation as resolved.

r := StorageSyncServerEndpointResource{}
listResourceAddress := "azurerm_storage_sync_server_endpoint.list"
data := acceptance.BuildTestData(t, "azurerm_storage_sync_server_endpoint", "test")

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.basicListQuery(data),
QueryResultChecks: []querycheck.QueryResultCheck{
querycheck.ExpectLengthAtLeast(listResourceAddress, 1),
},
},
},
})
}

func (r StorageSyncServerEndpointResource) basicListQuery(data acceptance.TestData) string {
return fmt.Sprintf(`
list "azurerm_storage_sync_server_endpoint" "list" {
provider = azurerm
config {
storage_sync_group_id = "/subscriptions/%s/resourceGroups/acctestRG-StorageSync-%d/providers/Microsoft.StorageSync/storageSyncServices/acctest-StorageSync-%d/syncGroups/acctest-StorageSyncGroup-%d"
}
}
`, data.Subscriptions.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger)
}
Loading
Loading