Skip to content

Commit b6bc9bc

Browse files
authored
Merge pull request #36511 from awsaxeman/f-aws-fsx-ontap_file_system-flexgroups
FSx ONTAP FlexGroup and Scale-out update
2 parents fc1b174 + cddf8d0 commit b6bc9bc

37 files changed

+1339
-1046
lines changed

.changelog/36511.txt

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
```release-note:enhancement
2+
resource/aws_fsx_ontap_file_system: Support up to 12 `ha_pairs`
3+
```
4+
5+
```release-note:enhancement
6+
resource/aws_fsx_ontap_file_system: Increase `storage_capacity` maximum to 1PiB
7+
```
8+
9+
```release-note:enhancement
10+
resource/aws_fsx_ontap_file_system: Update `throughput_capacity_per_ha_pair` to support all values from `throughput_capacity`
11+
```
12+
13+
```release-note:enhancement
14+
resource/aws_fsx_ontap_file_system: Add support for specifying 1 ha_pair with `SINGLE_AZ_1` and `MULTI_AZ_1` deployment types
15+
```
16+
17+
```release-note:enhancement
18+
resource/aws_fsx_ontap_volume: Add `aggregate_configuration` configuration block
19+
```
20+
21+
```release-note:enhancement
22+
resource/aws_fsx_ontap_volume: Add `size_in_bytes` and `volume_style` arguments
23+
```

.ci/.golangci2.yml

+4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ issues:
6262
- staticcheck
6363
path: "internal/service/firehose"
6464
text: "SA1019: \\w+.(\\w+) is deprecated: (\\w+) has been deprecated"
65+
- linters:
66+
- staticcheck
67+
path: "internal/service/fsx"
68+
text: "SA1019: \\w+.(\\w+) is deprecated: This property is deprecated"
6569
- linters:
6670
- staticcheck
6771
path: internal/service/globalaccelerator/

internal/sdkv2/types/nullable/int.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func ValidateTypeStringNullableInt(v interface{}, k string) (ws []string, es []e
6666

6767
// ValidateTypeStringNullableIntAtLeast provides custom error messaging for TypeString ints
6868
// Some arguments require an int value or unspecified, empty field.
69-
func ValidateTypeStringNullableIntAtLeast(min int) schema.SchemaValidateFunc {
69+
func ValidateTypeStringNullableIntAtLeast(min int64) schema.SchemaValidateFunc {
7070
return func(i interface{}, k string) (ws []string, es []error) {
7171
value, ok := i.(string)
7272
if !ok {
@@ -84,7 +84,7 @@ func ValidateTypeStringNullableIntAtLeast(min int) schema.SchemaValidateFunc {
8484
return
8585
}
8686

87-
if v < int64(min) {
87+
if v < min {
8888
es = append(es, fmt.Errorf("expected %s to be at least (%d), got %d", k, min, v))
8989
}
9090

@@ -94,7 +94,7 @@ func ValidateTypeStringNullableIntAtLeast(min int) schema.SchemaValidateFunc {
9494

9595
// ValidateTypeStringNullableIntBetween provides custom error messaging for TypeString ints
9696
// Some arguments require an int value or unspecified, empty field.
97-
func ValidateTypeStringNullableIntBetween(min int, max int) schema.SchemaValidateFunc {
97+
func ValidateTypeStringNullableIntBetween(min, max int64) schema.SchemaValidateFunc {
9898
return func(i interface{}, k string) (ws []string, es []error) {
9999
value, ok := i.(string)
100100
if !ok {
@@ -112,7 +112,7 @@ func ValidateTypeStringNullableIntBetween(min int, max int) schema.SchemaValidat
112112
return
113113
}
114114

115-
if v < int64(min) || v > int64(max) {
115+
if v < min || v > max {
116116
es = append(es, fmt.Errorf("expected %s to be at between (%d) and (%d), got %d", k, min, max, v))
117117
}
118118

internal/service/fsx/backup.go

+132-30
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import (
1414
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1515
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
1616
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"
17+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
1718
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1819
"github.com/hashicorp/terraform-provider-aws/internal/conns"
1920
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
21+
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
2022
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
2123
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
2224
"github.com/hashicorp/terraform-provider-aws/internal/verify"
@@ -25,12 +27,13 @@ import (
2527

2628
// @SDKResource("aws_fsx_backup", name="Backup")
2729
// @Tags(identifierAttribute="arn")
28-
func ResourceBackup() *schema.Resource {
30+
func resourceBackup() *schema.Resource {
2931
return &schema.Resource{
3032
CreateWithoutTimeout: resourceBackupCreate,
3133
ReadWithoutTimeout: resourceBackupRead,
3234
UpdateWithoutTimeout: resourceBackupUpdate,
3335
DeleteWithoutTimeout: resourceBackupDelete,
36+
3437
Importer: &schema.ResourceImporter{
3538
StateContext: schema.ImportStatePassthroughContext,
3639
},
@@ -102,34 +105,27 @@ func resourceBackupCreate(ctx context.Context, d *schema.ResourceData, meta inte
102105
return sdkdiag.AppendErrorf(diags, "creating FSx Backup: %s", "can only specify either file_system_id or volume_id")
103106
}
104107

105-
result, err := conn.CreateBackupWithContext(ctx, input)
108+
output, err := conn.CreateBackupWithContext(ctx, input)
109+
106110
if err != nil {
107111
return sdkdiag.AppendErrorf(diags, "creating FSx Backup: %s", err)
108112
}
109113

110-
d.SetId(aws.StringValue(result.Backup.BackupId))
114+
d.SetId(aws.StringValue(output.Backup.BackupId))
111115

112-
log.Println("[DEBUG] Waiting for FSx backup to become available")
113116
if _, err := waitBackupAvailable(ctx, conn, d.Id()); err != nil {
114-
return sdkdiag.AppendErrorf(diags, "waiting for FSx Backup (%s) to be available: %s", d.Id(), err)
117+
return sdkdiag.AppendErrorf(diags, "waiting for FSx Backup (%s) create: %s", d.Id(), err)
115118
}
116119

117120
return append(diags, resourceBackupRead(ctx, d, meta)...)
118121
}
119122

120-
func resourceBackupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
121-
var diags diag.Diagnostics
122-
123-
// Tags only.
124-
125-
return append(diags, resourceBackupRead(ctx, d, meta)...)
126-
}
127-
128123
func resourceBackupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
129124
var diags diag.Diagnostics
130125
conn := meta.(*conns.AWSClient).FSxConn(ctx)
131126

132-
backup, err := FindBackupByID(ctx, conn, d.Id())
127+
backup, err := findBackupByID(ctx, conn, d.Id())
128+
133129
if !d.IsNewResource() && tfresource.NotFound(err) {
134130
log.Printf("[WARN] FSx Backup (%s) not found, removing from state", d.Id())
135131
d.SetId("")
@@ -141,17 +137,12 @@ func resourceBackupRead(ctx context.Context, d *schema.ResourceData, meta interf
141137
}
142138

143139
d.Set("arn", backup.ResourceARN)
144-
d.Set("type", backup.Type)
145-
146140
if backup.FileSystem != nil {
147-
fs := backup.FileSystem
148-
d.Set("file_system_id", fs.FileSystemId)
141+
d.Set("file_system_id", backup.FileSystem.FileSystemId)
149142
}
150-
151143
d.Set("kms_key_id", backup.KmsKeyId)
152-
153144
d.Set("owner_id", backup.OwnerId)
154-
145+
d.Set("type", backup.Type)
155146
if backup.Volume != nil {
156147
d.Set("volume_id", backup.Volume.VolumeId)
157148
}
@@ -161,28 +152,139 @@ func resourceBackupRead(ctx context.Context, d *schema.ResourceData, meta interf
161152
return diags
162153
}
163154

155+
func resourceBackupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
156+
var diags diag.Diagnostics
157+
158+
// Tags only.
159+
160+
return append(diags, resourceBackupRead(ctx, d, meta)...)
161+
}
162+
164163
func resourceBackupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
165164
var diags diag.Diagnostics
166165
conn := meta.(*conns.AWSClient).FSxConn(ctx)
167166

168-
request := &fsx.DeleteBackupInput{
167+
log.Printf("[INFO] Deleting FSx Backup: %s", d.Id())
168+
_, err := conn.DeleteBackupWithContext(ctx, &fsx.DeleteBackupInput{
169169
BackupId: aws.String(d.Id()),
170-
}
170+
})
171171

172-
log.Printf("[INFO] Deleting FSx Backup: %s", d.Id())
173-
_, err := conn.DeleteBackupWithContext(ctx, request)
172+
if tfawserr.ErrCodeEquals(err, fsx.ErrCodeBackupNotFound) {
173+
return diags
174+
}
174175

175176
if err != nil {
176-
if tfawserr.ErrCodeEquals(err, fsx.ErrCodeBackupNotFound) {
177-
return diags
178-
}
179177
return sdkdiag.AppendErrorf(diags, "deleting FSx Backup (%s): %s", d.Id(), err)
180178
}
181179

182-
log.Println("[DEBUG] Waiting for backup to delete")
183180
if _, err := waitBackupDeleted(ctx, conn, d.Id()); err != nil {
184-
return sdkdiag.AppendErrorf(diags, "waiting for FSx Backup (%s) to deleted: %s", d.Id(), err)
181+
return sdkdiag.AppendErrorf(diags, "waiting for FSx Backup (%s) delete: %s", d.Id(), err)
185182
}
186183

187184
return diags
188185
}
186+
187+
func findBackupByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.Backup, error) {
188+
input := &fsx.DescribeBackupsInput{
189+
BackupIds: aws.StringSlice([]string{id}),
190+
}
191+
192+
return findBackup(ctx, conn, input, tfslices.PredicateTrue[*fsx.Backup]())
193+
}
194+
195+
func findBackup(ctx context.Context, conn *fsx.FSx, input *fsx.DescribeBackupsInput, filter tfslices.Predicate[*fsx.Backup]) (*fsx.Backup, error) {
196+
output, err := findBackups(ctx, conn, input, filter)
197+
198+
if err != nil {
199+
return nil, err
200+
}
201+
202+
return tfresource.AssertSinglePtrResult(output)
203+
}
204+
205+
func findBackups(ctx context.Context, conn *fsx.FSx, input *fsx.DescribeBackupsInput, filter tfslices.Predicate[*fsx.Backup]) ([]*fsx.Backup, error) {
206+
var output []*fsx.Backup
207+
208+
err := conn.DescribeBackupsPagesWithContext(ctx, input, func(page *fsx.DescribeBackupsOutput, lastPage bool) bool {
209+
if page == nil {
210+
return !lastPage
211+
}
212+
213+
for _, v := range page.Backups {
214+
if v != nil && filter(v) {
215+
output = append(output, v)
216+
}
217+
}
218+
219+
return !lastPage
220+
})
221+
222+
if tfawserr.ErrCodeEquals(err, fsx.ErrCodeFileSystemNotFound) || tfawserr.ErrCodeEquals(err, fsx.ErrCodeBackupNotFound) {
223+
return nil, &retry.NotFoundError{
224+
LastError: err,
225+
LastRequest: input,
226+
}
227+
}
228+
229+
if err != nil {
230+
return nil, err
231+
}
232+
233+
return output, nil
234+
}
235+
236+
func statusBackup(ctx context.Context, conn *fsx.FSx, id string) retry.StateRefreshFunc {
237+
return func() (interface{}, string, error) {
238+
output, err := findBackupByID(ctx, conn, id)
239+
240+
if tfresource.NotFound(err) {
241+
return nil, "", nil
242+
}
243+
244+
if err != nil {
245+
return nil, "", err
246+
}
247+
248+
return output, aws.StringValue(output.Lifecycle), nil
249+
}
250+
}
251+
252+
func waitBackupAvailable(ctx context.Context, conn *fsx.FSx, id string) (*fsx.Backup, error) {
253+
const (
254+
timeout = 10 * time.Minute
255+
)
256+
stateConf := &retry.StateChangeConf{
257+
Pending: []string{fsx.BackupLifecycleCreating, fsx.BackupLifecyclePending, fsx.BackupLifecycleTransferring},
258+
Target: []string{fsx.BackupLifecycleAvailable},
259+
Refresh: statusBackup(ctx, conn, id),
260+
Timeout: timeout,
261+
}
262+
263+
outputRaw, err := stateConf.WaitForStateContext(ctx)
264+
265+
if output, ok := outputRaw.(*fsx.Backup); ok {
266+
return output, err
267+
}
268+
269+
return nil, err
270+
}
271+
272+
func waitBackupDeleted(ctx context.Context, conn *fsx.FSx, id string) (*fsx.Backup, error) {
273+
const (
274+
timeout = 10 * time.Minute
275+
)
276+
stateConf := &retry.StateChangeConf{
277+
Pending: []string{fsx.FileSystemLifecycleDeleting},
278+
Target: []string{},
279+
Refresh: statusBackup(ctx, conn, id),
280+
Timeout: timeout,
281+
}
282+
283+
outputRaw, err := stateConf.WaitForStateContext(ctx)
284+
285+
if output, ok := outputRaw.(*fsx.Backup); ok {
286+
return output, err
287+
}
288+
289+
return nil, err
290+
}

0 commit comments

Comments
 (0)