Skip to content

Commit 798d151

Browse files
authored
Merge pull request #37868 from awsaxeman/f-aws-fsx-lustre_file_system-metadata
[new feature] fsx lustre file system metadata
2 parents 4110403 + 5a2755b commit 798d151

File tree

6 files changed

+310
-5
lines changed

6 files changed

+310
-5
lines changed

.changelog/37868.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/aws_fsx_lustre_file_system: Add `metadata_configuration` argument
3+
```

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/ProtonMail/go-crypto v1.1.0-alpha.2
77
github.com/YakDriver/go-version v0.1.0
88
github.com/YakDriver/regexache v0.23.0
9-
github.com/aws/aws-sdk-go v1.53.17
9+
github.com/aws/aws-sdk-go v1.53.18
1010
github.com/aws/aws-sdk-go-v2 v1.27.1
1111
github.com/aws/aws-sdk-go-v2/config v1.27.17
1212
github.com/aws/aws-sdk-go-v2/credentials v1.17.17

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
2222
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
2323
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
2424
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
25-
github.com/aws/aws-sdk-go v1.53.17 h1:TwtYMzVBTaqPVj/pcemHRIgk01OycWEcEUyUUX0tpCI=
26-
github.com/aws/aws-sdk-go v1.53.17/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
25+
github.com/aws/aws-sdk-go v1.53.18 h1:BeMeCK5e3bDGJj675FhnO94zRci8O35ombWXRvYomJs=
26+
github.com/aws/aws-sdk-go v1.53.18/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
2727
github.com/aws/aws-sdk-go-v2 v1.27.1 h1:xypCL2owhog46iFxBKKpBcw+bPTX/RJzwNj8uSilENw=
2828
github.com/aws/aws-sdk-go-v2 v1.27.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
2929
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=

internal/service/fsx/lustre_file_system.go

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,28 @@ func resourceLustreFileSystem() *schema.Resource {
179179
},
180180
},
181181
},
182+
"metadata_configuration": {
183+
Type: schema.TypeList,
184+
Optional: true,
185+
Computed: true,
186+
MaxItems: 1,
187+
Elem: &schema.Resource{
188+
Schema: map[string]*schema.Schema{
189+
names.AttrMode: {
190+
Type: schema.TypeString,
191+
Optional: true,
192+
Computed: true,
193+
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice(fsx.MetadataConfigurationMode_Values(), false)),
194+
},
195+
names.AttrIOPS: {
196+
Type: schema.TypeInt,
197+
Optional: true,
198+
Computed: true,
199+
ValidateDiagFunc: validation.ToDiagFunc(validation.IntInSlice([]int{1500, 3000, 6000, 12000, 24000, 36000, 48000, 60000, 72000, 84000, 96000, 108000, 120000, 132000, 144000, 156000, 168000, 180000, 192000})),
200+
},
201+
},
202+
},
203+
},
182204
"mount_name": {
183205
Type: schema.TypeString,
184206
Computed: true,
@@ -277,12 +299,13 @@ func resourceLustreFileSystem() *schema.Resource {
277299

278300
CustomizeDiff: customdiff.Sequence(
279301
verify.SetTagsDiff,
280-
resourceLustreFileSystemSchemaCustomizeDiff,
302+
resourceLustreFileSystemStorageCapacityCustomizeDiff,
303+
resourceLustreFileSystemMetadataConfigCustomizeDiff,
281304
),
282305
}
283306
}
284307

285-
func resourceLustreFileSystemSchemaCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error {
308+
func resourceLustreFileSystemStorageCapacityCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta any) error {
286309
// we want to force a new resource if the new storage capacity is less than the old one
287310
if d.HasChange("storage_capacity") {
288311
o, n := d.GetChange("storage_capacity")
@@ -296,6 +319,51 @@ func resourceLustreFileSystemSchemaCustomizeDiff(_ context.Context, d *schema.Re
296319
return nil
297320
}
298321

322+
func resourceLustreFileSystemMetadataConfigCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta any) error {
323+
//metadata_configuration is only supported when deployment_type is persistent2
324+
if v, ok := d.GetOk("metadata_configuration"); ok {
325+
if len(v.([]any)) > 0 {
326+
deploymentType := d.Get("deployment_type").(string)
327+
if deploymentType != fsx.LustreDeploymentTypePersistent2 {
328+
return fmt.Errorf("metadata_configuration can only be set when deployment type is " + fsx.LustreDeploymentTypePersistent2)
329+
}
330+
}
331+
}
332+
333+
// we want to force a new resource if the new Iops is less than the old one
334+
if d.HasChange("metadata_configuration") {
335+
if v, ok := d.GetOk("metadata_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
336+
if mode := d.Get("metadata_configuration.0.mode"); mode == fsx.MetadataConfigurationModeUserProvisioned {
337+
o, n := d.GetChange("metadata_configuration")
338+
339+
oldV := o.([]interface{})
340+
newV := n.([]interface{})
341+
var metaOld map[string]interface{}
342+
var metaNew map[string]interface{}
343+
344+
for _, v := range oldV {
345+
metaOld = v.(map[string]interface{})
346+
}
347+
348+
for _, v := range newV {
349+
metaNew = v.(map[string]interface{})
350+
}
351+
352+
if len(metaNew) > 0 && len(metaOld) > 0 {
353+
if metaNew[names.AttrIOPS].(int) < metaOld[names.AttrIOPS].(int) {
354+
log.Printf("[DEBUG] Forcing new due to metadata iops decrease. old iops: %d new iops: %d", metaOld[names.AttrIOPS].(int), metaNew[names.AttrIOPS].(int))
355+
if err := d.ForceNew("metadata_configuration.0.iops"); err != nil {
356+
return err
357+
}
358+
}
359+
}
360+
}
361+
}
362+
}
363+
364+
return nil
365+
}
366+
299367
func resourceLustreFileSystemCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
300368
var diags diag.Diagnostics
301369
conn := meta.(*conns.AWSClient).FSxConn(ctx)
@@ -382,6 +450,11 @@ func resourceLustreFileSystemCreate(ctx context.Context, d *schema.ResourceData,
382450
inputB.LustreConfiguration.LogConfiguration = expandLustreLogCreateConfiguration(v.([]interface{}))
383451
}
384452

453+
if v, ok := d.GetOk("metadata_configuration"); ok && len(v.([]interface{})) > 0 {
454+
inputC.LustreConfiguration.MetadataConfiguration = expandLustreMetadataCreateConfiguration(v.([]interface{}))
455+
inputB.LustreConfiguration.MetadataConfiguration = expandLustreMetadataCreateConfiguration(v.([]interface{}))
456+
}
457+
385458
if v, ok := d.GetOk("per_unit_storage_throughput"); ok {
386459
inputC.LustreConfiguration.PerUnitStorageThroughput = aws.Int64(int64(v.(int)))
387460
inputB.LustreConfiguration.PerUnitStorageThroughput = aws.Int64(int64(v.(int)))
@@ -469,6 +542,9 @@ func resourceLustreFileSystemRead(ctx context.Context, d *schema.ResourceData, m
469542
if err := d.Set("log_configuration", flattenLustreLogConfiguration(lustreConfig.LogConfiguration)); err != nil {
470543
return sdkdiag.AppendErrorf(diags, "setting log_configuration: %s", err)
471544
}
545+
if err := d.Set("metadata_configuration", flattenLustreMetadataConfiguration(lustreConfig.MetadataConfiguration)); err != nil {
546+
return sdkdiag.AppendErrorf(diags, "setting metadata_configuration: %s", err)
547+
}
472548
d.Set("mount_name", lustreConfig.MountName)
473549
d.Set("network_interface_ids", aws.StringValueSlice(filesystem.NetworkInterfaceIds))
474550
d.Set(names.AttrOwnerID, filesystem.OwnerId)
@@ -518,6 +594,10 @@ func resourceLustreFileSystemUpdate(ctx context.Context, d *schema.ResourceData,
518594
input.LustreConfiguration.LogConfiguration = expandLustreLogCreateConfiguration(d.Get("log_configuration").([]interface{}))
519595
}
520596

597+
if d.HasChange("metadata_configuration") {
598+
input.LustreConfiguration.MetadataConfiguration = expandLustreMetadataUpdateConfiguration(d.Get("metadata_configuration").([]interface{}))
599+
}
600+
521601
if d.HasChange("per_unit_storage_throughput") {
522602
input.LustreConfiguration.PerUnitStorageThroughput = aws.Int64(int64(d.Get("per_unit_storage_throughput").(int)))
523603
}
@@ -647,6 +727,56 @@ func flattenLustreLogConfiguration(adopts *fsx.LustreLogConfiguration) []map[str
647727
return []map[string]interface{}{m}
648728
}
649729

730+
func expandLustreMetadataCreateConfiguration(l []interface{}) *fsx.CreateFileSystemLustreMetadataConfiguration {
731+
if len(l) == 0 || l[0] == nil {
732+
return nil
733+
}
734+
735+
data := l[0].(map[string]interface{})
736+
req := &fsx.CreateFileSystemLustreMetadataConfiguration{
737+
Mode: aws.String(data[names.AttrMode].(string)),
738+
}
739+
740+
if v, ok := data[names.AttrIOPS].(int); ok && v != 0 {
741+
req.Iops = aws.Int64(int64(v))
742+
}
743+
744+
return req
745+
}
746+
747+
func expandLustreMetadataUpdateConfiguration(l []interface{}) *fsx.UpdateFileSystemLustreMetadataConfiguration {
748+
if len(l) == 0 || l[0] == nil {
749+
return nil
750+
}
751+
752+
data := l[0].(map[string]interface{})
753+
req := &fsx.UpdateFileSystemLustreMetadataConfiguration{
754+
Mode: aws.String(data[names.AttrMode].(string)),
755+
}
756+
757+
if v, ok := data[names.AttrIOPS].(int); ok && v != 0 {
758+
req.Iops = aws.Int64(int64(v))
759+
}
760+
761+
return req
762+
}
763+
764+
func flattenLustreMetadataConfiguration(adopts *fsx.FileSystemLustreMetadataConfiguration) []map[string]interface{} {
765+
if adopts == nil {
766+
return []map[string]interface{}{}
767+
}
768+
769+
m := map[string]interface{}{
770+
names.AttrMode: aws.StringValue(adopts.Mode),
771+
}
772+
773+
if adopts.Iops != nil {
774+
m[names.AttrIOPS] = aws.Int64Value(adopts.Iops)
775+
}
776+
777+
return []map[string]interface{}{m}
778+
}
779+
650780
func logStateFunc(v interface{}) string {
651781
value := v.(string)
652782
// API returns the specific log stream arn instead of provided log group

internal/service/fsx/lustre_file_system_test.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func TestAccFSxLustreFileSystem_basic(t *testing.T) {
5353
resource.TestCheckResourceAttr(resourceName, "imported_file_chunk_size", acctest.Ct0),
5454
resource.TestCheckResourceAttr(resourceName, "log_configuration.#", acctest.Ct1),
5555
resource.TestCheckResourceAttr(resourceName, "log_configuration.0.level", "DISABLED"),
56+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", acctest.Ct0),
5657
resource.TestCheckResourceAttrSet(resourceName, "mount_name"),
5758
resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", acctest.Ct2),
5859
acctest.CheckResourceAttrAccountID(resourceName, names.AttrOwnerID),
@@ -768,6 +769,130 @@ func TestAccFSxLustreFileSystem_logConfig(t *testing.T) {
768769
})
769770
}
770771

772+
func TestAccFSxLustreFileSystem_metadataConfig(t *testing.T) {
773+
ctx := acctest.Context(t)
774+
var filesystem1, filesystem2 fsx.FileSystem
775+
resourceName := "aws_fsx_lustre_file_system.test"
776+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
777+
778+
resource.ParallelTest(t, resource.TestCase{
779+
PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) },
780+
ErrorCheck: acctest.ErrorCheck(t, names.FSxServiceID),
781+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
782+
CheckDestroy: testAccCheckLustreFileSystemDestroy(ctx),
783+
Steps: []resource.TestStep{
784+
{
785+
Config: testAccLustreFileSystemConfig_metadata(rName, "AUTOMATIC"),
786+
Check: resource.ComposeTestCheckFunc(
787+
testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem1),
788+
testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem1),
789+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", acctest.Ct1),
790+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "AUTOMATIC"),
791+
resource.TestCheckResourceAttrSet(resourceName, "metadata_configuration.0.iops"),
792+
),
793+
},
794+
{
795+
ResourceName: resourceName,
796+
ImportState: true,
797+
ImportStateVerify: true,
798+
ImportStateVerifyIgnore: []string{names.AttrSecurityGroupIDs},
799+
},
800+
{
801+
Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500),
802+
Check: resource.ComposeTestCheckFunc(
803+
testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2),
804+
testAccCheckLustreFileSystemNotRecreated(&filesystem1, &filesystem2),
805+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", acctest.Ct1),
806+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "USER_PROVISIONED"),
807+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.iops", "1500"),
808+
),
809+
},
810+
},
811+
})
812+
}
813+
814+
func TestAccFSxLustreFileSystem_metadataConfig_increase(t *testing.T) {
815+
ctx := acctest.Context(t)
816+
var filesystem1, filesystem2 fsx.FileSystem
817+
resourceName := "aws_fsx_lustre_file_system.test"
818+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
819+
820+
resource.ParallelTest(t, resource.TestCase{
821+
PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) },
822+
ErrorCheck: acctest.ErrorCheck(t, names.FSxServiceID),
823+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
824+
CheckDestroy: testAccCheckLustreFileSystemDestroy(ctx),
825+
Steps: []resource.TestStep{
826+
{
827+
Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500),
828+
Check: resource.ComposeTestCheckFunc(
829+
testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem1),
830+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", acctest.Ct1),
831+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "USER_PROVISIONED"),
832+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.iops", "1500"),
833+
),
834+
},
835+
{
836+
ResourceName: resourceName,
837+
ImportState: true,
838+
ImportStateVerify: true,
839+
ImportStateVerifyIgnore: []string{names.AttrSecurityGroupIDs},
840+
},
841+
{
842+
Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 3000),
843+
Check: resource.ComposeTestCheckFunc(
844+
testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2),
845+
testAccCheckLustreFileSystemNotRecreated(&filesystem1, &filesystem2),
846+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", acctest.Ct1),
847+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "USER_PROVISIONED"),
848+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.iops", "3000"),
849+
),
850+
},
851+
},
852+
})
853+
}
854+
855+
func TestAccFSxLustreFileSystem_metadataConfig_decrease(t *testing.T) {
856+
ctx := acctest.Context(t)
857+
var filesystem1, filesystem2 fsx.FileSystem
858+
resourceName := "aws_fsx_lustre_file_system.test"
859+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
860+
861+
resource.ParallelTest(t, resource.TestCase{
862+
PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) },
863+
ErrorCheck: acctest.ErrorCheck(t, names.FSxServiceID),
864+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
865+
CheckDestroy: testAccCheckLustreFileSystemDestroy(ctx),
866+
Steps: []resource.TestStep{
867+
{
868+
Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 3000),
869+
Check: resource.ComposeTestCheckFunc(
870+
testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem1),
871+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", acctest.Ct1),
872+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "USER_PROVISIONED"),
873+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.iops", "3000"),
874+
),
875+
},
876+
{
877+
ResourceName: resourceName,
878+
ImportState: true,
879+
ImportStateVerify: true,
880+
ImportStateVerifyIgnore: []string{names.AttrSecurityGroupIDs},
881+
},
882+
{
883+
Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500),
884+
Check: resource.ComposeTestCheckFunc(
885+
testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2),
886+
testAccCheckLustreFileSystemRecreated(&filesystem1, &filesystem2),
887+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", acctest.Ct1),
888+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "USER_PROVISIONED"),
889+
resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.iops", "1500"),
890+
),
891+
},
892+
},
893+
})
894+
}
895+
771896
func TestAccFSxLustreFileSystem_rootSquashConfig(t *testing.T) {
772897
ctx := acctest.Context(t)
773898
var filesystem fsx.FileSystem
@@ -1608,6 +1733,45 @@ resource "aws_fsx_lustre_file_system" "test" {
16081733
`, rName, status))
16091734
}
16101735

1736+
func testAccLustreFileSystemConfig_metadata(rName, mode string) string {
1737+
return acctest.ConfigCompose(testAccLustreFileSystemConfig_base(rName), fmt.Sprintf(`
1738+
resource "aws_fsx_lustre_file_system" "test" {
1739+
storage_capacity = 1200
1740+
subnet_ids = aws_subnet.test[*].id
1741+
deployment_type = "PERSISTENT_2"
1742+
per_unit_storage_throughput = 125
1743+
1744+
metadata_configuration {
1745+
mode = %[2]q
1746+
}
1747+
1748+
tags = {
1749+
Name = %[1]q
1750+
}
1751+
}
1752+
`, rName, mode))
1753+
}
1754+
1755+
func testAccLustreFileSystemConfig_metadata_iops(rName, mode string, iops int) string {
1756+
return acctest.ConfigCompose(testAccLustreFileSystemConfig_base(rName), fmt.Sprintf(`
1757+
resource "aws_fsx_lustre_file_system" "test" {
1758+
storage_capacity = 1200
1759+
subnet_ids = aws_subnet.test[*].id
1760+
deployment_type = "PERSISTENT_2"
1761+
per_unit_storage_throughput = 125
1762+
1763+
metadata_configuration {
1764+
mode = %[2]q
1765+
iops = %[3]d
1766+
}
1767+
1768+
tags = {
1769+
Name = %[1]q
1770+
}
1771+
}
1772+
`, rName, mode, iops))
1773+
}
1774+
16111775
func testAccLustreFileSystemConfig_rootSquash(rName, uid string) string {
16121776
return acctest.ConfigCompose(testAccLustreFileSystemConfig_base(rName), fmt.Sprintf(`
16131777
resource "aws_fsx_lustre_file_system" "test" {

0 commit comments

Comments
 (0)