diff --git a/.changelog/20569.txt b/.changelog/20569.txt new file mode 100644 index 00000000000..bb5efca3619 --- /dev/null +++ b/.changelog/20569.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_fsx_backup +``` \ No newline at end of file diff --git a/aws/internal/service/fsx/finder/finder.go b/aws/internal/service/fsx/finder/finder.go new file mode 100644 index 00000000000..c74a509b431 --- /dev/null +++ b/aws/internal/service/fsx/finder/finder.go @@ -0,0 +1,36 @@ +package finder + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/fsx" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func BackupByID(conn *fsx.FSx, id string) (*fsx.Backup, error) { + input := &fsx.DescribeBackupsInput{ + BackupIds: aws.StringSlice([]string{id}), + } + + output, err := conn.DescribeBackups(input) + + if tfawserr.ErrCodeEquals(err, fsx.ErrCodeFileSystemNotFound) || tfawserr.ErrCodeEquals(err, fsx.ErrCodeBackupNotFound) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || len(output.Backups) == 0 || output.Backups[0] == nil { + return nil, &resource.NotFoundError{ + Message: "Empty result", + LastRequest: input, + } + } + + return output.Backups[0], nil +} diff --git a/aws/internal/service/fsx/waiter/status.go b/aws/internal/service/fsx/waiter/status.go new file mode 100644 index 00000000000..eaaa05bc09e --- /dev/null +++ b/aws/internal/service/fsx/waiter/status.go @@ -0,0 +1,25 @@ +package waiter + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/fsx" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/fsx/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" +) + +func BackupStatus(conn *fsx.FSx, id string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := finder.BackupByID(conn, id) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, aws.StringValue(output.Lifecycle), nil + } +} diff --git a/aws/internal/service/fsx/waiter/waiter.go b/aws/internal/service/fsx/waiter/waiter.go new file mode 100644 index 00000000000..4edfce96421 --- /dev/null +++ b/aws/internal/service/fsx/waiter/waiter.go @@ -0,0 +1,47 @@ +package waiter + +import ( + "time" + + "github.com/aws/aws-sdk-go/service/fsx" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +const ( + BackupAvailableTimeout = 10 * time.Minute + BackupDeletedTimeout = 10 * time.Minute +) + +func BackupAvailable(conn *fsx.FSx, id string) (*fsx.Backup, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{fsx.BackupLifecycleCreating, fsx.BackupLifecyclePending, fsx.BackupLifecycleTransferring}, + Target: []string{fsx.BackupLifecycleAvailable}, + Refresh: BackupStatus(conn, id), + Timeout: BackupAvailableTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if output, ok := outputRaw.(*fsx.Backup); ok { + return output, err + } + + return nil, err +} + +func BackupDeleted(conn *fsx.FSx, id string) (*fsx.Backup, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{fsx.FileSystemLifecycleDeleting}, + Target: []string{}, + Refresh: BackupStatus(conn, id), + Timeout: BackupDeletedTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if output, ok := outputRaw.(*fsx.Backup); ok { + return output, err + } + + return nil, err +} diff --git a/aws/provider.go b/aws/provider.go index 1beb5e9c100..fc256f58722 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -766,6 +766,7 @@ func Provider() *schema.Provider { "aws_emr_managed_scaling_policy": resourceAwsEMRManagedScalingPolicy(), "aws_emr_security_configuration": resourceAwsEMRSecurityConfiguration(), "aws_flow_log": resourceAwsFlowLog(), + "aws_fsx_backup": resourceAwsFsxBackup(), "aws_fsx_lustre_file_system": resourceAwsFsxLustreFileSystem(), "aws_fsx_windows_file_system": resourceAwsFsxWindowsFileSystem(), "aws_fms_admin_account": resourceAwsFmsAdminAccount(), diff --git a/aws/resource_aws_fsx_backup.go b/aws/resource_aws_fsx_backup.go new file mode 100644 index 00000000000..7c8b4b8aa41 --- /dev/null +++ b/aws/resource_aws_fsx_backup.go @@ -0,0 +1,173 @@ +package aws + +import ( + "fmt" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/fsx" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/fsx/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/fsx/waiter" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" +) + +func resourceAwsFsxBackup() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsFsxBackupCreate, + Read: resourceAwsFsxBackupRead, + Update: resourceAwsFsxBackupUpdate, + Delete: resourceAwsFsxBackupDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "file_system_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "kms_key_id": { + Type: schema.TypeString, + Computed: true, + }, + "owner_id": { + Type: schema.TypeString, + Computed: true, + }, + "tags": tagsSchemaComputed(), + "tags_all": tagsSchemaComputed(), + "type": { + Type: schema.TypeString, + Computed: true, + }, + }, + + CustomizeDiff: customdiff.Sequence( + SetTagsDiff, + ), + } +} + +func resourceAwsFsxBackupCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).fsxconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig + tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{}))) + + input := &fsx.CreateBackupInput{ + ClientRequestToken: aws.String(resource.UniqueId()), + FileSystemId: aws.String(d.Get("file_system_id").(string)), + } + + if len(tags) > 0 { + input.Tags = tags.IgnoreAws().FsxTags() + } + + result, err := conn.CreateBackup(input) + if err != nil { + return fmt.Errorf("error creating FSx Backup: %w", err) + } + + d.SetId(aws.StringValue(result.Backup.BackupId)) + + log.Println("[DEBUG] Waiting for FSx backup to become available") + if _, err := waiter.BackupAvailable(conn, d.Id()); err != nil { + return fmt.Errorf("error waiting for FSx Backup (%s) to be available: %w", d.Id(), err) + } + + return resourceAwsFsxBackupRead(d, meta) +} + +func resourceAwsFsxBackupUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).fsxconn + + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") + + if err := keyvaluetags.FsxUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating FSx Backup (%s) tags: %w", d.Get("arn").(string), err) + } + } + + return resourceAwsFsxBackupRead(d, meta) +} + +func resourceAwsFsxBackupRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).fsxconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig + ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig + + backup, err := finder.BackupByID(conn, d.Id()) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] FSx Backup (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("error reading FSx Backup (%s): %w", d.Id(), err) + } + + d.Set("arn", backup.ResourceARN) + d.Set("type", backup.Type) + + fs := backup.FileSystem + d.Set("file_system_id", fs.FileSystemId) + + d.Set("kms_key_id", backup.KmsKeyId) + + d.Set("owner_id", backup.OwnerId) + + tags := keyvaluetags.FsxKeyValueTags(backup.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig) + + //lintignore:AWSR002 + if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { + return fmt.Errorf("error setting tags: %w", err) + } + + if err := d.Set("tags_all", tags.Map()); err != nil { + return fmt.Errorf("error setting tags_all: %w", err) + } + + return nil +} + +func resourceAwsFsxBackupDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).fsxconn + + request := &fsx.DeleteBackupInput{ + BackupId: aws.String(d.Id()), + } + + log.Printf("[INFO] Deleting FSx Backup: %s", d.Id()) + _, err := conn.DeleteBackup(request) + + if err != nil { + if tfawserr.ErrCodeEquals(err, fsx.ErrCodeBackupNotFound) { + return nil + } + return fmt.Errorf("error deleting FSx Backup (%s): %w", d.Id(), err) + } + + log.Println("[DEBUG] Waiting for filesystem to delete") + if _, err := waiter.BackupDeleted(conn, d.Id()); err != nil { + return fmt.Errorf("error waiting for FSx Backup (%s) to deleted: %w", d.Id(), err) + } + + return nil +} diff --git a/aws/resource_aws_fsx_backup_test.go b/aws/resource_aws_fsx_backup_test.go new file mode 100644 index 00000000000..a82439c0776 --- /dev/null +++ b/aws/resource_aws_fsx_backup_test.go @@ -0,0 +1,340 @@ +package aws + +import ( + "fmt" + "log" + "regexp" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/fsx" + multierror "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/fsx/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" +) + +func init() { + resource.AddTestSweepers("aws_fsx_backup", &resource.Sweeper{ + Name: "aws_fsx_backup", + F: testSweepFSXBackups, + }) +} + +func testSweepFSXBackups(region string) error { + client, err := sharedClientForRegion(region) + + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + + conn := client.(*AWSClient).fsxconn + sweepResources := make([]*testSweepResource, 0) + var errs *multierror.Error + input := &fsx.DescribeBackupsInput{} + + err = conn.DescribeBackupsPages(input, func(page *fsx.DescribeBackupsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, fs := range page.Backups { + r := resourceAwsFsxBackup() + d := r.Data(nil) + d.SetId(aws.StringValue(fs.BackupId)) + + sweepResources = append(sweepResources, NewTestSweepResource(r, d, client)) + } + + return !lastPage + }) + + if err != nil { + errs = multierror.Append(errs, fmt.Errorf("error listing FSx Backups for %s: %w", region, err)) + } + + if err = testSweepResourceOrchestrator(sweepResources); err != nil { + errs = multierror.Append(errs, fmt.Errorf("error sweeping FSx Backups for %s: %w", region, err)) + } + + if testSweepSkipSweepError(errs.ErrorOrNil()) { + log.Printf("[WARN] Skipping FSx Backups sweep for %s: %s", region, errs) + return nil + } + + return errs.ErrorOrNil() +} + +func TestAccAWSFsxBackup_basic(t *testing.T) { + var backup fsx.Backup + resourceName := "aws_fsx_backup.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(fsx.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, fsx.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckFsxBackupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsFsxBackupConfigBasic(), + Check: resource.ComposeTestCheckFunc( + testAccCheckFsxBackupExists(resourceName, &backup), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "fsx", regexp.MustCompile(`backup/.+`)), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSFsxBackup_disappears(t *testing.T) { + var backup fsx.Backup + resourceName := "aws_fsx_backup.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(fsx.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, fsx.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckFsxBackupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsFsxBackupConfigBasic(), + Check: resource.ComposeTestCheckFunc( + testAccCheckFsxBackupExists(resourceName, &backup), + testAccCheckResourceDisappears(testAccProvider, resourceAwsFsxBackup(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAWSFsxBackup_disappears_filesystem(t *testing.T) { + var backup fsx.Backup + resourceName := "aws_fsx_backup.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(fsx.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, fsx.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckFsxBackupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsFsxBackupConfigBasic(), + Check: resource.ComposeTestCheckFunc( + testAccCheckFsxBackupExists(resourceName, &backup), + testAccCheckResourceDisappears(testAccProvider, resourceAwsFsxLustreFileSystem(), "aws_fsx_lustre_file_system.test"), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAWSFsxBackup_tags(t *testing.T) { + var backup fsx.Backup + resourceName := "aws_fsx_backup.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(fsx.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, fsx.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckFsxBackupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsFsxBackupConfigTags1("key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFsxBackupExists(resourceName, &backup), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAwsFsxBackupConfigTags2("key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFsxBackupExists(resourceName, &backup), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAwsFsxBackupConfigTags1("key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFsxBackupExists(resourceName, &backup), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + +func TestAccAWSFsxBackup_implictTags(t *testing.T) { + var backup fsx.Backup + resourceName := "aws_fsx_backup.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(fsx.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, fsx.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckFsxBackupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsFsxBackupConfigImplictTags("key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFsxBackupExists(resourceName, &backup), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckFsxBackupExists(resourceName string, fs *fsx.Backup) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).fsxconn + + output, err := finder.BackupByID(conn, rs.Primary.ID) + if err != nil { + return err + } + + if output == nil { + return fmt.Errorf("FSx Backup (%s) not found", rs.Primary.ID) + } + + *fs = *output + + return nil + } +} + +func testAccCheckFsxBackupDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).fsxconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_fsx_backup" { + continue + } + + _, err := finder.BackupByID(conn, rs.Primary.ID) + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("FSx Backup %s still exists", rs.Primary.ID) + } + return nil +} + +func testAccAwsFsxBackupConfigBase() string { + return composeConfig(testAccAvailableAZsNoOptInConfig(), ` +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "test1" { + vpc_id = aws_vpc.test.id + cidr_block = "10.0.1.0/24" + availability_zone = data.aws_availability_zones.available.names[0] +} + +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 +} +`) +} + +func testAccAwsFsxBackupConfigBasic() string { + return composeConfig(testAccAwsFsxBackupConfigBase(), ` +resource "aws_fsx_backup" "test" { + file_system_id = aws_fsx_lustre_file_system.test.id +} +`) +} + +func testAccAwsFsxBackupConfigTags1(tagKey1, tagValue1 string) string { + return composeConfig(testAccAwsFsxBackupConfigBase(), fmt.Sprintf(` +resource "aws_fsx_backup" "test" { + file_system_id = aws_fsx_lustre_file_system.test.id + + tags = { + %[1]q = %[2]q + } +} +`, tagKey1, tagValue1)) +} + +func testAccAwsFsxBackupConfigTags2(tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return composeConfig(testAccAwsFsxBackupConfigBase(), fmt.Sprintf(` +resource "aws_fsx_backup" "test" { + file_system_id = aws_fsx_lustre_file_system.test.id + + tags = { + %[1]q = %[2]q + %[3]q = %[4]q + } +} +`, tagKey1, tagValue1, tagKey2, tagValue2)) +} + +func testAccAwsFsxBackupConfigImplictTags(tagKey1, tagValue1 string) string { + return composeConfig(testAccAvailableAZsNoOptInConfig(), fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "test1" { + vpc_id = aws_vpc.test.id + cidr_block = "10.0.1.0/24" + availability_zone = data.aws_availability_zones.available.names[0] +} + +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 + copy_tags_to_backups = true + + tags = { + %[1]q = %[2]q + } +} + +resource "aws_fsx_backup" "test" { + file_system_id = aws_fsx_lustre_file_system.test.id +} +`, tagKey1, tagValue1)) +} diff --git a/website/docs/r/fsx_backup.html.markdown b/website/docs/r/fsx_backup.html.markdown new file mode 100644 index 00000000000..c5dc53c76a7 --- /dev/null +++ b/website/docs/r/fsx_backup.html.markdown @@ -0,0 +1,60 @@ +--- +subcategory: "File System (FSx)" +layout: "aws" +page_title: "AWS: aws_fsx_backup" +description: |- + Manages a FSx Backup. +--- + +# Resource: aws_fsx_backup + +Provides a FSx Backup resource. + +## Example Usage + +```terraform +resource "aws_fsx_backup" "example" { + file_system_id = aws_fsx_lustre_file_system.example.id +} + +resource "aws_fsx_lustre_file_system" "example" { + storage_capacity = 1200 + subnet_ids = [aws_subnet.example.id] + deployment_type = "PERSISTENT_1" + per_unit_storage_throughput = 50 +} +``` + +## Argument Reference + +The following arguments are supported: + +* `file_system_id` - (Required) The ID of the file system to back up. +* `tags` - (Optional) A map of tags to assign to the file system. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. If you have set `copy_tags_to_backups` to true, and you specify one or more tags, no existing file system tags are copied from the file system to the backup. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `arn` - Amazon Resource Name of the backup. +* `id` - Identifier of the backup, e.g. `fs-12345678` +* `kms_key_id` - The ID of the AWS Key Management Service (AWS KMS) key used to encrypt the backup of the Amazon FSx file system's data at rest. +* `owner_id` - AWS account identifier that created the file system. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). +* `type` - The type of the file system backup. + +## Timeouts + +`aws_fsx_backup` provides the following [Timeouts](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts) +configuration options: + +* `create` - (Default `10m`) How long to wait for the backup to be created. +* `delete` - (Default `10m`) How long to wait for the backup to be deleted. + +## Import + +FSx Backups can be imported using the `id`, e.g. + +``` +$ terraform import aws_fsx_backup.example fs-543ab12b1ca672f33 +```