Skip to content

Commit

Permalink
Merge pull request #14446 from DrFaust92/r/fsx_lustre_fs_renetion
Browse files Browse the repository at this point in the history
r/fsx_lustre_file_system - add support for backup retention
  • Loading branch information
breathingdust authored Sep 18, 2020
2 parents e01d93c + b3d7c8d commit 5dd5ded
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 70 deletions.
14 changes: 14 additions & 0 deletions aws/fsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,17 @@ func waitForFsxFileSystemDeletion(conn *fsx.FSx, id string, timeout time.Duratio

return err
}

func waitForFsxFileSystemUpdate(conn *fsx.FSx, id string, timeout time.Duration) error {
stateConf := &resource.StateChangeConf{
Pending: []string{fsx.FileSystemLifecycleUpdating},
Target: []string{fsx.FileSystemLifecycleAvailable},
Refresh: refreshFsxFileSystemLifecycle(conn, id),
Timeout: timeout,
Delay: 30 * time.Second,
}

_, err := stateConf.WaitForState()

return err
}
97 changes: 48 additions & 49 deletions aws/resource_aws_fsx_lustre_file_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ func resourceAwsFsxLustreFileSystem() *schema.Resource {
200,
}),
},
"automatic_backup_retention_days": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ValidateFunc: validation.IntBetween(0, 35),
},
},
}
}
Expand All @@ -143,29 +149,24 @@ func resourceAwsFsxLustreFileSystemCreate(d *schema.ResourceData, meta interface
FileSystemType: aws.String(fsx.FileSystemTypeLustre),
StorageCapacity: aws.Int64(int64(d.Get("storage_capacity").(int))),
SubnetIds: expandStringList(d.Get("subnet_ids").([]interface{})),
LustreConfiguration: &fsx.CreateFileSystemLustreConfiguration{
DeploymentType: aws.String(d.Get("deployment_type").(string)),
},
}

if v, ok := d.GetOk("export_path"); ok {
if input.LustreConfiguration == nil {
input.LustreConfiguration = &fsx.CreateFileSystemLustreConfiguration{}
}
if v, ok := d.GetOk("automatic_backup_retention_days"); ok {
input.LustreConfiguration.AutomaticBackupRetentionDays = aws.Int64(int64(v.(int)))
}

if v, ok := d.GetOk("export_path"); ok {
input.LustreConfiguration.ExportPath = aws.String(v.(string))
}

if v, ok := d.GetOk("import_path"); ok {
if input.LustreConfiguration == nil {
input.LustreConfiguration = &fsx.CreateFileSystemLustreConfiguration{}
}

input.LustreConfiguration.ImportPath = aws.String(v.(string))
}

if v, ok := d.GetOk("imported_file_chunk_size"); ok {
if input.LustreConfiguration == nil {
input.LustreConfiguration = &fsx.CreateFileSystemLustreConfiguration{}
}

input.LustreConfiguration.ImportedFileChunkSize = aws.Int64(int64(v.(int)))
}

Expand All @@ -178,40 +179,24 @@ func resourceAwsFsxLustreFileSystemCreate(d *schema.ResourceData, meta interface
}

if v, ok := d.GetOk("weekly_maintenance_start_time"); ok {
if input.LustreConfiguration == nil {
input.LustreConfiguration = &fsx.CreateFileSystemLustreConfiguration{}
}

input.LustreConfiguration.WeeklyMaintenanceStartTime = aws.String(v.(string))
}

if v, ok := d.GetOk("deployment_type"); ok {
if input.LustreConfiguration == nil {
input.LustreConfiguration = &fsx.CreateFileSystemLustreConfiguration{}
}

input.LustreConfiguration.DeploymentType = aws.String(v.(string))
}

if v, ok := d.GetOk("per_unit_storage_throughput"); ok {
if input.LustreConfiguration == nil {
input.LustreConfiguration = &fsx.CreateFileSystemLustreConfiguration{}
}

input.LustreConfiguration.PerUnitStorageThroughput = aws.Int64(int64(v.(int)))
}

result, err := conn.CreateFileSystem(input)
if err != nil {
return fmt.Errorf("Error creating FSx filesystem: %s", err)
return fmt.Errorf("Error creating FSx Lustre filesystem: %w", err)
}

d.SetId(*result.FileSystem.FileSystemId)
d.SetId(aws.StringValue(result.FileSystem.FileSystemId))

log.Println("[DEBUG] Waiting for filesystem to become available")

if err := waitForFsxFileSystemCreation(conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
return fmt.Errorf("Error waiting for filesystem (%s) to become available: %s", d.Id(), err)
return fmt.Errorf("Error waiting for filesystem (%s) to become available: %w", d.Id(), err)
}

return resourceAwsFsxLustreFileSystemRead(d, meta)
Expand All @@ -224,7 +209,7 @@ func resourceAwsFsxLustreFileSystemUpdate(d *schema.ResourceData, meta interface
o, n := d.GetChange("tags")

if err := keyvaluetags.FsxUpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
return fmt.Errorf("error updating FSx Windows File System (%s) tags: %s", d.Get("arn").(string), err)
return fmt.Errorf("error updating FSx Lustre File System (%s) tags: %w", d.Get("arn").(string), err)
}
}

Expand All @@ -240,10 +225,21 @@ func resourceAwsFsxLustreFileSystemUpdate(d *schema.ResourceData, meta interface
requestUpdate = true
}

if d.HasChange("automatic_backup_retention_days") {
input.LustreConfiguration.AutomaticBackupRetentionDays = aws.Int64(int64(d.Get("automatic_backup_retention_days").(int)))
requestUpdate = true
}

if requestUpdate {
_, err := conn.UpdateFileSystem(input)
if err != nil {
return fmt.Errorf("error updating FSX File System (%s): %s", d.Id(), err)
return fmt.Errorf("error updating FSX Lustre File System (%s): %w", d.Id(), err)
}

log.Println("[DEBUG] Waiting for filesystem to become available")

if err := waitForFsxFileSystemUpdate(conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
return fmt.Errorf("Error waiting for filesystem (%s) to become available: %w", d.Id(), err)
}
}

Expand All @@ -263,7 +259,7 @@ func resourceAwsFsxLustreFileSystemRead(d *schema.ResourceData, meta interface{}
}

if err != nil {
return fmt.Errorf("Error reading FSx File System (%s): %s", d.Id(), err)
return fmt.Errorf("Error reading FSx Lustre File System (%s): %w", d.Id(), err)
}

if filesystem == nil {
Expand All @@ -272,46 +268,49 @@ func resourceAwsFsxLustreFileSystemRead(d *schema.ResourceData, meta interface{}
return nil
}

lustreConfig := filesystem.LustreConfiguration

if filesystem.WindowsConfiguration != nil {
return fmt.Errorf("expected FSx Lustre File System, found FSx Windows File System: %s", d.Id())
}

if filesystem.LustreConfiguration == nil {
if lustreConfig == nil {
return fmt.Errorf("error describing FSx Lustre File System (%s): empty Lustre configuration", d.Id())
}

if filesystem.LustreConfiguration.DataRepositoryConfiguration == nil {
if lustreConfig.DataRepositoryConfiguration == nil {
// Initialize an empty structure to simplify d.Set() handling
filesystem.LustreConfiguration.DataRepositoryConfiguration = &fsx.DataRepositoryConfiguration{}
lustreConfig.DataRepositoryConfiguration = &fsx.DataRepositoryConfiguration{}
}

d.Set("arn", filesystem.ResourceARN)
d.Set("dns_name", filesystem.DNSName)
d.Set("export_path", filesystem.LustreConfiguration.DataRepositoryConfiguration.ExportPath)
d.Set("import_path", filesystem.LustreConfiguration.DataRepositoryConfiguration.ImportPath)
d.Set("imported_file_chunk_size", filesystem.LustreConfiguration.DataRepositoryConfiguration.ImportedFileChunkSize)
d.Set("deployment_type", filesystem.LustreConfiguration.DeploymentType)
if filesystem.LustreConfiguration.PerUnitStorageThroughput != nil {
d.Set("per_unit_storage_throughput", filesystem.LustreConfiguration.PerUnitStorageThroughput)
d.Set("export_path", lustreConfig.DataRepositoryConfiguration.ExportPath)
d.Set("import_path", lustreConfig.DataRepositoryConfiguration.ImportPath)
d.Set("imported_file_chunk_size", lustreConfig.DataRepositoryConfiguration.ImportedFileChunkSize)
d.Set("deployment_type", lustreConfig.DeploymentType)
if lustreConfig.PerUnitStorageThroughput != nil {
d.Set("per_unit_storage_throughput", lustreConfig.PerUnitStorageThroughput)
}

if err := d.Set("network_interface_ids", aws.StringValueSlice(filesystem.NetworkInterfaceIds)); err != nil {
return fmt.Errorf("error setting network_interface_ids: %s", err)
return fmt.Errorf("error setting network_interface_ids: %w", err)
}

d.Set("owner_id", filesystem.OwnerId)
d.Set("storage_capacity", filesystem.StorageCapacity)

if err := d.Set("subnet_ids", aws.StringValueSlice(filesystem.SubnetIds)); err != nil {
return fmt.Errorf("error setting subnet_ids: %s", err)
return fmt.Errorf("error setting subnet_ids: %w", err)
}

if err := d.Set("tags", keyvaluetags.FsxKeyValueTags(filesystem.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %s", err)
return fmt.Errorf("error setting tags: %w", err)
}

d.Set("vpc_id", filesystem.VpcId)
d.Set("weekly_maintenance_start_time", filesystem.LustreConfiguration.WeeklyMaintenanceStartTime)
d.Set("weekly_maintenance_start_time", lustreConfig.WeeklyMaintenanceStartTime)
d.Set("automatic_backup_retention_days", lustreConfig.AutomaticBackupRetentionDays)

return nil
}
Expand All @@ -330,13 +329,13 @@ func resourceAwsFsxLustreFileSystemDelete(d *schema.ResourceData, meta interface
}

if err != nil {
return fmt.Errorf("Error deleting FSx filesystem: %s", err)
return fmt.Errorf("Error deleting FSx Lustre filesystem: %w", err)
}

log.Println("[DEBUG] Waiting for filesystem to delete")

if err := waitForFsxFileSystemDeletion(conn, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil {
return fmt.Errorf("Error waiting for filesystem (%s) to delete: %s", d.Id(), err)
return fmt.Errorf("Error waiting for filesystem (%s) to delete: %w", d.Id(), err)
}

return nil
Expand Down
75 changes: 56 additions & 19 deletions aws/resource_aws_fsx_lustre_file_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func TestAccAWSFsxLustreFileSystem_basic(t *testing.T) {
resource.TestMatchResourceAttr(resourceName, "vpc_id", regexp.MustCompile(`^vpc-.+`)),
resource.TestMatchResourceAttr(resourceName, "weekly_maintenance_start_time", regexp.MustCompile(`^\d:\d\d:\d\d$`)),
resource.TestCheckResourceAttr(resourceName, "deployment_type", fsx.LustreDeploymentTypeScratch1),
resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "0"),
),
},
{
Expand Down Expand Up @@ -124,7 +125,7 @@ func TestAccAWSFsxLustreFileSystem_disappears(t *testing.T) {
Config: testAccAwsFsxLustreFileSystemConfigSubnetIds1(),
Check: resource.ComposeTestCheckFunc(
testAccCheckFsxLustreFileSystemExists(resourceName, &filesystem),
testAccCheckFsxLustreFileSystemDisappears(&filesystem),
testAccCheckResourceDisappears(testAccProvider, resourceAwsFsxLustreFileSystem(), resourceName),
),
ExpectNonEmptyPlan: true,
},
Expand Down Expand Up @@ -387,6 +388,47 @@ func TestAccAWSFsxLustreFileSystem_WeeklyMaintenanceStartTime(t *testing.T) {
})
}

func TestAccAWSFsxLustreFileSystem_automaticBackupRetentionDays(t *testing.T) {
var filesystem1, filesystem2 fsx.FileSystem
resourceName := "aws_fsx_lustre_file_system.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckFsxLustreFileSystemDestroy,
Steps: []resource.TestStep{
{
Config: testAccAwsFsxLustreFileSystemConfigAutomaticBackupRetentionDays(1),
Check: resource.ComposeTestCheckFunc(
testAccCheckFsxLustreFileSystemExists(resourceName, &filesystem1),
resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"security_group_ids"},
},
{
Config: testAccAwsFsxLustreFileSystemConfigAutomaticBackupRetentionDays(0),
Check: resource.ComposeTestCheckFunc(
testAccCheckFsxLustreFileSystemExists(resourceName, &filesystem2),
testAccCheckFsxLustreFileSystemNotRecreated(&filesystem1, &filesystem2),
resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "0"),
),
},
{
Config: testAccAwsFsxLustreFileSystemConfigAutomaticBackupRetentionDays(1),
Check: resource.ComposeTestCheckFunc(
testAccCheckFsxLustreFileSystemExists(resourceName, &filesystem1),
resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "1"),
),
},
},
})
}

func TestAccAWSFsxLustreFileSystem_DeploymentTypePersistent1(t *testing.T) {
var filesystem fsx.FileSystem
resourceName := "aws_fsx_lustre_file_system.test"
Expand All @@ -403,6 +445,7 @@ func TestAccAWSFsxLustreFileSystem_DeploymentTypePersistent1(t *testing.T) {
// per_unit_storage_throughput is only available with deployment_type=PERSISTENT_1, so we test both here.
resource.TestCheckResourceAttr(resourceName, "per_unit_storage_throughput", "50"),
resource.TestCheckResourceAttr(resourceName, "deployment_type", fsx.LustreDeploymentTypePersistent1),
resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "0"),
),
},
{
Expand Down Expand Up @@ -491,24 +534,6 @@ func testAccCheckFsxLustreFileSystemDestroy(s *terraform.State) error {
return nil
}

func testAccCheckFsxLustreFileSystemDisappears(filesystem *fsx.FileSystem) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).fsxconn

input := &fsx.DeleteFileSystemInput{
FileSystemId: filesystem.FileSystemId,
}

_, err := conn.DeleteFileSystem(input)

if err != nil {
return err
}

return waitForFsxFileSystemDeletion(conn, aws.StringValue(filesystem.FileSystemId), 30*time.Minute)
}
}

func testAccCheckFsxLustreFileSystemNotRecreated(i, j *fsx.FileSystem) resource.TestCheckFunc {
return func(s *terraform.State) error {
if aws.StringValue(i.FileSystemId) != aws.StringValue(j.FileSystemId) {
Expand Down Expand Up @@ -731,6 +756,18 @@ resource "aws_fsx_lustre_file_system" "test" {
`, weeklyMaintenanceStartTime)
}

func testAccAwsFsxLustreFileSystemConfigAutomaticBackupRetentionDays(retention int) string {
return testAccAwsFsxLustreFileSystemConfigBase() + fmt.Sprintf(`
resource "aws_fsx_lustre_file_system" "test" {
storage_capacity = 1200
subnet_ids = ["${aws_subnet.test1.id}"]
deployment_type = "PERSISTENT_1"
per_unit_storage_throughput = 50
automatic_backup_retention_days = %[1]d
}
`, retention)
}

func testAccAwsFsxLustreFileSystemDeploymentType(deploymentType string) string {
return testAccAwsFsxLustreFileSystemConfigBase() + fmt.Sprintf(`
resource "aws_fsx_lustre_file_system" "test" {
Expand Down
5 changes: 3 additions & 2 deletions website/docs/r/fsx_lustre_file_system.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ The following arguments are supported:
* `security_group_ids` - (Optional) A list of IDs for the security groups that apply to the specified network interfaces created for file system access. These security groups will apply to all network interfaces.
* `tags` - (Optional) A map of tags to assign to the file system.
* `weekly_maintenance_start_time` - (Optional) The preferred start time (in `d:HH:MM` format) to perform weekly maintenance, in the UTC time zone.
* `deployment_type` - (Optional) - The filesystem deployment type. One of: `SCRATCH_1`, `SCRATCH_2`, `PERSISTENT_1`.
* `per_unit_storage_throughput` - (Optional) - Describes the amount of read and write throughput for each 1 tebibyte of storage, in MB/s/TiB, required for the `PERSISTENT_1` deployment_type. For valid values, see the [AWS documentation](https://docs.aws.amazon.com/fsx/latest/APIReference/API_CreateFileSystemLustreConfiguration.html).
* `deployment_type` - (Optional) The filesystem deployment type. One of: `SCRATCH_1`, `SCRATCH_2`, `PERSISTENT_1`.
* `per_unit_storage_throughput` - (Optional) Describes the amount of read and write throughput for each 1 tebibyte of storage, in MB/s/TiB, required for the `PERSISTENT_1` deployment_type. For valid values, see the [AWS documentation](https://docs.aws.amazon.com/fsx/latest/APIReference/API_CreateFileSystemLustreConfiguration.html).
* `automatic_backup_retention_days` - (Optional) The number of days to retain automatic backups. Setting this to 0 disables automatic backups. You can retain automatic backups for a maximum of 35 days. only valid for `PERSISTENT_1` deployment_type.

## Attributes Reference

Expand Down

0 comments on commit 5dd5ded

Please sign in to comment.