Skip to content

Commit

Permalink
Merge pull request #18006 from shuheiktgw/add_efs_backup_policy_resource
Browse files Browse the repository at this point in the history
Add efs_file_system_backup_policy resource
  • Loading branch information
ewbankkit authored Jun 23, 2021
2 parents 8740daf + f7af1ea commit 3e77a11
Show file tree
Hide file tree
Showing 10 changed files with 552 additions and 26 deletions.
3 changes: 3 additions & 0 deletions .changelog/18006.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_efs_backup_policy
```
36 changes: 36 additions & 0 deletions aws/internal/service/efs/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/efs"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func BackupPolicyByID(conn *efs.EFS, id string) (*efs.BackupPolicy, error) {
input := &efs.DescribeBackupPolicyInput{
FileSystemId: aws.String(id),
}

output, err := conn.DescribeBackupPolicy(input)

if tfawserr.ErrCodeEquals(err, efs.ErrCodeFileSystemNotFound) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.BackupPolicy == nil {
return nil, &resource.NotFoundError{
Message: "Empty result",
LastRequest: input,
}
}

return output.BackupPolicy, nil
}
18 changes: 18 additions & 0 deletions aws/internal/service/efs/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/efs"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/efs/finder"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

// AccessPointLifeCycleState fetches the Access Point and its LifecycleState
Expand All @@ -29,6 +31,22 @@ func AccessPointLifeCycleState(conn *efs.EFS, accessPointId string) resource.Sta
}
}

func BackupPolicyStatus(conn *efs.EFS, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := finder.BackupPolicyByID(conn, id)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, aws.StringValue(output.Status), nil
}
}

// FileSystemLifeCycleState fetches the Access Point and its LifecycleState
func FileSystemLifeCycleState(conn *efs.EFS, fileSystemID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
Expand Down
39 changes: 38 additions & 1 deletion aws/internal/service/efs/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const (
FileSystemDeletedTimeout = 10 * time.Minute
FileSystemDeletedDelayTimeout = 2 * time.Second
FileSystemDeletedMinTimeout = 3 * time.Second

BackupPolicyDisabledTimeout = 10 * time.Minute
BackupPolicyEnabledTimeout = 10 * time.Minute
)

// AccessPointCreated waits for an Operation to return Success
Expand All @@ -37,7 +40,7 @@ func AccessPointCreated(conn *efs.EFS, accessPointId string) (*efs.AccessPointDe
return nil, err
}

// AccessPointDelete waits for an Access Point to return Deleted
// AccessPointDeleted waits for an Access Point to return Deleted
func AccessPointDeleted(conn *efs.EFS, accessPointId string) (*efs.AccessPointDescription, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{efs.LifeCycleStateAvailable, efs.LifeCycleStateDeleting, efs.LifeCycleStateDeleted},
Expand Down Expand Up @@ -94,3 +97,37 @@ func FileSystemDeleted(conn *efs.EFS, fileSystemID string) (*efs.FileSystemDescr

return nil, err
}

func BackupPolicyDisabled(conn *efs.EFS, id string) (*efs.BackupPolicy, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{efs.StatusDisabling},
Target: []string{efs.StatusDisabled},
Refresh: BackupPolicyStatus(conn, id),
Timeout: BackupPolicyDisabledTimeout,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*efs.BackupPolicy); ok {
return output, err
}

return nil, err
}

func BackupPolicyEnabled(conn *efs.EFS, id string) (*efs.BackupPolicy, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{efs.StatusEnabling},
Target: []string{efs.StatusEnabled},
Refresh: BackupPolicyStatus(conn, id),
Timeout: BackupPolicyEnabledTimeout,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*efs.BackupPolicy); 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 @@ -715,6 +715,7 @@ func Provider() *schema.Provider {
"aws_ecs_service": resourceAwsEcsService(),
"aws_ecs_task_definition": resourceAwsEcsTaskDefinition(),
"aws_efs_access_point": resourceAwsEfsAccessPoint(),
"aws_efs_backup_policy": resourceAwsEfsBackupPolicy(),
"aws_efs_file_system": resourceAwsEfsFileSystem(),
"aws_efs_file_system_policy": resourceAwsEfsFileSystemPolicy(),
"aws_efs_mount_target": resourceAwsEfsMountTarget(),
Expand Down
8 changes: 4 additions & 4 deletions aws/resource_aws_backup_vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,13 @@ func resourceAwsBackupVaultUpdate(d *schema.ResourceData, meta interface{}) erro
func resourceAwsBackupVaultDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).backupconn

input := &backup.DeleteBackupVaultInput{
log.Printf("[DEBUG] Deleting Backup Vault: %s", d.Id())
_, err := conn.DeleteBackupVault(&backup.DeleteBackupVaultInput{
BackupVaultName: aws.String(d.Id()),
}
})

_, err := conn.DeleteBackupVault(input)
if err != nil {
return fmt.Errorf("error deleting Backup Vault (%s): %s", d.Id(), err)
return fmt.Errorf("error deleting Backup Vault (%s): %w", d.Id(), err)
}

return nil
Expand Down
65 changes: 44 additions & 21 deletions aws/resource_aws_backup_vault_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ package aws
import (
"fmt"
"log"
"strings"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/backup"
"github.com/hashicorp/go-multierror"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
Expand All @@ -31,35 +30,59 @@ func testSweepBackupVaults(region string) error {
if err != nil {
return fmt.Errorf("Error getting client: %w", err)
}

conn := client.(*AWSClient).backupconn
sweepResources := make([]*testSweepResource, 0)
var errs *multierror.Error

input := &backup.ListBackupVaultsInput{}
var sweeperErrs *multierror.Error
sweepResources := make([]*testSweepResource, 0)

err = conn.ListBackupVaultsPages(input, func(page *backup.ListBackupVaultsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, vault := range page.BackupVaultList {
if vault == nil {
continue
failedToDeleteRecoveryPoint := false
name := aws.StringValue(vault.BackupVaultName)
input := &backup.ListRecoveryPointsByBackupVaultInput{
BackupVaultName: aws.String(name),
}

name := aws.StringValue(vault.BackupVaultName)
err := conn.ListRecoveryPointsByBackupVaultPages(input, func(page *backup.ListRecoveryPointsByBackupVaultOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, recoveryPoint := range page.RecoveryPoints {
arn := aws.StringValue(recoveryPoint.RecoveryPointArn)

log.Printf("[INFO] Deleting Recovery Point (%s) in Backup Vault (%s)", arn, name)
_, err := conn.DeleteRecoveryPoint(&backup.DeleteRecoveryPointInput{
BackupVaultName: aws.String(name),
RecoveryPointArn: aws.String(arn),
})

// Ignore Default Backup Vault in region (cannot be deleted)
// and automated Backups that result in AccessDeniedException when deleted
if name == "Default" || strings.Contains(name, "automatic-backup-vault") {
if err != nil {
log.Printf("[WARN] Failed to delete Recovery Point (%s) in Backup Vault (%s): %s", arn, name, err)
failedToDeleteRecoveryPoint = true
}
}

return !lastPage
})

if err != nil {
sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Reovery Points in Backup Vault (%s) for %s: %w", name, region, err))
}

// Ignore Default and Automatic EFS Backup Vaults in region (cannot be deleted)
if name == "Default" || name == "aws/efs/automatic-backup-vault" {
log.Printf("[INFO] Skipping Backup Vault: %s", name)
continue
}

// Backup Vault deletion only supported when empty
// Reference: https://docs.aws.amazon.com/aws-backup/latest/devguide/API_DeleteBackupVault.html
if aws.Int64Value(vault.NumberOfRecoveryPoints) != 0 {
if failedToDeleteRecoveryPoint {
log.Printf("[INFO] Skipping Backup Vault (%s): not empty", name)
continue
}
Expand All @@ -74,20 +97,20 @@ func testSweepBackupVaults(region string) error {
return !lastPage
})

if err != nil {
errs = multierror.Append(errs, fmt.Errorf("error listing Backup Vaults for %s: %w", region, err))
if testSweepSkipSweepError(err) {
log.Printf("[WARN] Skipping Backup Vaults sweep for %s: %s", region, err)
return sweeperErrs.ErrorOrNil()
}

if err := testSweepResourceOrchestrator(sweepResources); err != nil {
errs = multierror.Append(errs, fmt.Errorf("error sweeping Backup Vaults for %s: %w", region, err))
if err != nil {
sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Backup Vaults for %s: %w", region, err))
}

if testSweepSkipSweepError(errs.ErrorOrNil()) {
log.Printf("[WARN] Skipping Backup Vaults sweep for %s: %s", region, errs)
return nil
if err := testSweepResourceOrchestrator(sweepResources); err != nil {
sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error sweeping Backup Vaults for %s: %w", region, err))
}

return errs.ErrorOrNil()
return sweeperErrs.ErrorOrNil()
}

func TestAccAwsBackupVault_basic(t *testing.T) {
Expand Down
Loading

0 comments on commit 3e77a11

Please sign in to comment.