Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/fsx_lustre_file_system - add support for backup retention #14446

Merged
merged 4 commits into from
Sep 18, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
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 @@ -129,6 +129,12 @@ func resourceAwsFsxLustreFileSystem() *schema.Resource {
200,
}),
},
"automatic_backup_retention_days": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ValidateFunc: validation.IntBetween(0, 35),
},
},
}
}
Expand All @@ -141,29 +147,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 @@ -176,40 +177,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 @@ -222,7 +207,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 @@ -238,10 +223,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 @@ -261,7 +257,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 @@ -270,46 +266,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 @@ -328,13 +327,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