Skip to content

Commit b9219a7

Browse files
New Resource: azurerm_storage_mover_smb_mount_endpoint
1 parent a43b4db commit b9219a7

File tree

4 files changed

+652
-0
lines changed

4 files changed

+652
-0
lines changed

internal/services/storagemover/registration.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func (r Registration) Resources() []sdk.Resource {
4646
StorageMoverTargetEndpointResource{},
4747
StorageMoverProjectResource{},
4848
StorageMoverJobDefinitionResource{},
49+
StorageMoverSmbMountEndpointResource{},
4950
}
5051
}
5152

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package storagemover
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"regexp"
10+
"time"
11+
12+
"github.com/hashicorp/go-azure-helpers/lang/pointer"
13+
"github.com/hashicorp/go-azure-helpers/lang/response"
14+
"github.com/hashicorp/go-azure-sdk/resource-manager/storagemover/2025-07-01/endpoints"
15+
"github.com/hashicorp/go-azure-sdk/resource-manager/storagemover/2025-07-01/storagemovers"
16+
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
17+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
18+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
19+
)
20+
21+
type StorageMoverSmbMountEndpointModel struct {
22+
Name string `tfschema:"name"`
23+
StorageMoverId string `tfschema:"storage_mover_id"`
24+
Host string `tfschema:"host"`
25+
ShareName string `tfschema:"share_name"`
26+
UsernameUri string `tfschema:"username_uri"`
27+
PasswordUri string `tfschema:"password_uri"`
28+
Description string `tfschema:"description"`
29+
}
30+
31+
type StorageMoverSmbMountEndpointResource struct{}
32+
33+
var _ sdk.ResourceWithUpdate = StorageMoverSmbMountEndpointResource{}
34+
35+
func (r StorageMoverSmbMountEndpointResource) ResourceType() string {
36+
return "azurerm_storage_mover_smb_mount_endpoint"
37+
}
38+
39+
func (r StorageMoverSmbMountEndpointResource) ModelObject() interface{} {
40+
return &StorageMoverSmbMountEndpointModel{}
41+
}
42+
43+
func (r StorageMoverSmbMountEndpointResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
44+
return endpoints.ValidateEndpointID
45+
}
46+
47+
func (r StorageMoverSmbMountEndpointResource) Arguments() map[string]*pluginsdk.Schema {
48+
return map[string]*pluginsdk.Schema{
49+
"name": {
50+
Type: pluginsdk.TypeString,
51+
Required: true,
52+
ForceNew: true,
53+
ValidateFunc: validation.StringMatch(
54+
regexp.MustCompile(`^[0-9a-zA-Z][-_0-9a-zA-Z]{0,63}$`),
55+
`The name must be between 1 and 64 characters in length, begin with a letter or number, and may contain letters, numbers, dashes and underscore.`,
56+
),
57+
},
58+
59+
"storage_mover_id": {
60+
Type: pluginsdk.TypeString,
61+
Required: true,
62+
ForceNew: true,
63+
ValidateFunc: storagemovers.ValidateStorageMoverID,
64+
},
65+
66+
"host": {
67+
Type: pluginsdk.TypeString,
68+
Required: true,
69+
ForceNew: true,
70+
ValidateFunc: validation.StringIsNotEmpty,
71+
},
72+
73+
"share_name": {
74+
Type: pluginsdk.TypeString,
75+
Required: true,
76+
ForceNew: true,
77+
ValidateFunc: validation.StringIsNotEmpty,
78+
},
79+
80+
"username_uri": {
81+
Type: pluginsdk.TypeString,
82+
Optional: true,
83+
ValidateFunc: validation.StringIsNotEmpty,
84+
},
85+
86+
"password_uri": {
87+
Type: pluginsdk.TypeString,
88+
Optional: true,
89+
Sensitive: true,
90+
ValidateFunc: validation.StringIsNotEmpty,
91+
},
92+
93+
"description": {
94+
Type: pluginsdk.TypeString,
95+
Optional: true,
96+
ValidateFunc: validation.StringIsNotEmpty,
97+
},
98+
}
99+
}
100+
101+
func (r StorageMoverSmbMountEndpointResource) Attributes() map[string]*pluginsdk.Schema {
102+
return map[string]*pluginsdk.Schema{}
103+
}
104+
105+
func (r StorageMoverSmbMountEndpointResource) Create() sdk.ResourceFunc {
106+
return sdk.ResourceFunc{
107+
Timeout: 30 * time.Minute,
108+
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
109+
var model StorageMoverSmbMountEndpointModel
110+
if err := metadata.Decode(&model); err != nil {
111+
return fmt.Errorf("decoding: %+v", err)
112+
}
113+
114+
client := metadata.Client.StorageMover.EndpointsClient
115+
storageMoverId, err := storagemovers.ParseStorageMoverID(model.StorageMoverId)
116+
if err != nil {
117+
return err
118+
}
119+
120+
id := endpoints.NewEndpointID(storageMoverId.SubscriptionId, storageMoverId.ResourceGroupName, storageMoverId.StorageMoverName, model.Name)
121+
existing, err := client.Get(ctx, id)
122+
if err != nil && !response.WasNotFound(existing.HttpResponse) {
123+
return fmt.Errorf("checking for existing %s: %+v", id, err)
124+
}
125+
126+
if !response.WasNotFound(existing.HttpResponse) {
127+
return metadata.ResourceRequiresImport(r.ResourceType(), id)
128+
}
129+
130+
endpointProperties := endpoints.SmbMountEndpointProperties{
131+
Host: model.Host,
132+
ShareName: model.ShareName,
133+
}
134+
135+
if model.UsernameUri != "" || model.PasswordUri != "" {
136+
endpointProperties.Credentials = &endpoints.AzureKeyVaultSmbCredentials{
137+
Type: endpoints.CredentialTypeAzureKeyVaultSmb,
138+
UsernameUri: pointer.To(model.UsernameUri),
139+
PasswordUri: pointer.To(model.PasswordUri),
140+
}
141+
}
142+
143+
if model.Description != "" {
144+
endpointProperties.Description = pointer.To(model.Description)
145+
}
146+
147+
properties := endpoints.Endpoint{
148+
Properties: endpointProperties,
149+
}
150+
151+
if _, err := client.CreateOrUpdate(ctx, id, properties); err != nil {
152+
return fmt.Errorf("creating %s: %+v", id, err)
153+
}
154+
155+
metadata.SetID(id)
156+
return nil
157+
},
158+
}
159+
}
160+
161+
func (r StorageMoverSmbMountEndpointResource) Update() sdk.ResourceFunc {
162+
return sdk.ResourceFunc{
163+
Timeout: 30 * time.Minute,
164+
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
165+
client := metadata.Client.StorageMover.EndpointsClient
166+
167+
id, err := endpoints.ParseEndpointID(metadata.ResourceData.Id())
168+
if err != nil {
169+
return err
170+
}
171+
172+
var model StorageMoverSmbMountEndpointModel
173+
if err := metadata.Decode(&model); err != nil {
174+
return fmt.Errorf("decoding: %+v", err)
175+
}
176+
177+
resp, err := client.Get(ctx, *id)
178+
if err != nil {
179+
return fmt.Errorf("retrieving %s: %+v", *id, err)
180+
}
181+
182+
properties := resp.Model
183+
if properties == nil {
184+
return fmt.Errorf("retrieving %s: model was nil", *id)
185+
}
186+
187+
if v, ok := properties.Properties.(endpoints.SmbMountEndpointProperties); ok {
188+
if metadata.ResourceData.HasChange("description") {
189+
v.Description = pointer.To(model.Description)
190+
}
191+
192+
if metadata.ResourceData.HasChange("username_uri") || metadata.ResourceData.HasChange("password_uri") {
193+
if model.UsernameUri != "" || model.PasswordUri != "" {
194+
v.Credentials = &endpoints.AzureKeyVaultSmbCredentials{
195+
Type: endpoints.CredentialTypeAzureKeyVaultSmb,
196+
UsernameUri: pointer.To(model.UsernameUri),
197+
PasswordUri: pointer.To(model.PasswordUri),
198+
}
199+
} else {
200+
v.Credentials = nil
201+
}
202+
}
203+
204+
properties.Properties = v
205+
}
206+
207+
if _, err := client.CreateOrUpdate(ctx, *id, *properties); err != nil {
208+
return fmt.Errorf("updating %s: %+v", *id, err)
209+
}
210+
211+
return nil
212+
},
213+
}
214+
}
215+
216+
func (r StorageMoverSmbMountEndpointResource) Read() sdk.ResourceFunc {
217+
return sdk.ResourceFunc{
218+
Timeout: 5 * time.Minute,
219+
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
220+
client := metadata.Client.StorageMover.EndpointsClient
221+
222+
id, err := endpoints.ParseEndpointID(metadata.ResourceData.Id())
223+
if err != nil {
224+
return err
225+
}
226+
227+
resp, err := client.Get(ctx, *id)
228+
if err != nil {
229+
if response.WasNotFound(resp.HttpResponse) {
230+
return metadata.MarkAsGone(id)
231+
}
232+
233+
return fmt.Errorf("retrieving %s: %+v", *id, err)
234+
}
235+
236+
state := StorageMoverSmbMountEndpointModel{
237+
Name: id.EndpointName,
238+
StorageMoverId: storagemovers.NewStorageMoverID(id.SubscriptionId, id.ResourceGroupName, id.StorageMoverName).ID(),
239+
}
240+
241+
if model := resp.Model; model != nil {
242+
if v, ok := model.Properties.(endpoints.SmbMountEndpointProperties); ok {
243+
state.Host = v.Host
244+
state.ShareName = v.ShareName
245+
246+
if v.Credentials != nil {
247+
if v.Credentials.UsernameUri != nil {
248+
state.UsernameUri = *v.Credentials.UsernameUri
249+
}
250+
if v.Credentials.PasswordUri != nil {
251+
state.PasswordUri = *v.Credentials.PasswordUri
252+
}
253+
}
254+
255+
des := ""
256+
if v.Description != nil {
257+
des = *v.Description
258+
}
259+
state.Description = des
260+
}
261+
}
262+
263+
return metadata.Encode(&state)
264+
},
265+
}
266+
}
267+
268+
func (r StorageMoverSmbMountEndpointResource) Delete() sdk.ResourceFunc {
269+
return sdk.ResourceFunc{
270+
Timeout: 30 * time.Minute,
271+
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
272+
client := metadata.Client.StorageMover.EndpointsClient
273+
274+
id, err := endpoints.ParseEndpointID(metadata.ResourceData.Id())
275+
if err != nil {
276+
return err
277+
}
278+
279+
if err := client.DeleteThenPoll(ctx, *id); err != nil {
280+
return fmt.Errorf("deleting %s: %+v", id, err)
281+
}
282+
283+
return nil
284+
},
285+
}
286+
}

0 commit comments

Comments
 (0)