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

Fsx backup - new resource #20569

Merged
merged 11 commits into from
Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from 8 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
3 changes: 3 additions & 0 deletions .changelog/20569.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_fsx_backup
```
36 changes: 36 additions & 0 deletions aws/internal/service/fsx/finder/finder.go
Original file line number Diff line number Diff line change
@@ -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
}
25 changes: 25 additions & 0 deletions aws/internal/service/fsx/waiter/status.go
Original file line number Diff line number Diff line change
@@ -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
}
}
47 changes: 47 additions & 0 deletions aws/internal/service/fsx/waiter/waiter.go
Original file line number Diff line number Diff line change
@@ -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
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
174 changes: 174 additions & 0 deletions aws/resource_aws_fsx_backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
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(),
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
"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)
DrFaust92 marked this conversation as resolved.
Show resolved Hide resolved
}

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)
DrFaust92 marked this conversation as resolved.
Show resolved Hide resolved
}

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 Lustre File System (%s) tags: %w", d.Get("arn").(string), err)
DrFaust92 marked this conversation as resolved.
Show resolved Hide resolved
}
}

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)

if backup.KmsKeyId != nil {
d.Set("kms_key_id", backup.KmsKeyId)
}
DrFaust92 marked this conversation as resolved.
Show resolved Hide resolved

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()),
}

_, err := conn.DeleteBackup(request)
DrFaust92 marked this conversation as resolved.
Show resolved Hide resolved

if err != nil {
if tfawserr.ErrCodeEquals(err, fsx.ErrCodeBackupNotFound) {
return nil
}
return fmt.Errorf("Error deleting FSx Backup (%s): %w", d.Id(), err)
DrFaust92 marked this conversation as resolved.
Show resolved Hide resolved
}

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)
DrFaust92 marked this conversation as resolved.
Show resolved Hide resolved
}

return nil
}
Loading