Skip to content

Commit

Permalink
Merge pull request #20874 from DrFaust92/r/efs_fs_transition_to_prima…
Browse files Browse the repository at this point in the history
…ry_storage_class

r/efs_file_system - support transition to primary storage class
  • Loading branch information
ewbankkit authored Sep 13, 2021
2 parents 56b168c + ea92c95 commit 9b0205d
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 321 deletions.
3 changes: 3 additions & 0 deletions .changelog/20874.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_efs_file_system: Add `lifecycle_policy.transition_to_primary_storage_class` argument to support Intelligent-Tiering
```
25 changes: 25 additions & 0 deletions aws/internal/service/efs/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@ func BackupPolicyByID(conn *efs.EFS, id string) (*efs.BackupPolicy, error) {
return output.BackupPolicy, nil
}

func FileSystemByID(conn *efs.EFS, id string) (*efs.FileSystemDescription, error) {
input := &efs.DescribeFileSystemsInput{
FileSystemId: aws.String(id),
}

output, err := conn.DescribeFileSystems(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.FileSystems == nil || len(output.FileSystems) == 0 || output.FileSystems[0] == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.FileSystems[0], nil
}

func FileSystemPolicyByID(conn *efs.EFS, id string) (*efs.DescribeFileSystemPolicyOutput, error) {
input := &efs.DescribeFileSystemPolicyInput{
FileSystemId: aws.String(id),
Expand Down
19 changes: 6 additions & 13 deletions aws/internal/service/efs/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,18 @@ func BackupPolicyStatus(conn *efs.EFS, id string) resource.StateRefreshFunc {
}
}

// FileSystemLifeCycleState fetches the Access Point and its LifecycleState
func FileSystemLifeCycleState(conn *efs.EFS, fileSystemID string) resource.StateRefreshFunc {
func FileSystemLifeCycleState(conn *efs.EFS, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &efs.DescribeFileSystemsInput{
FileSystemId: aws.String(fileSystemID),
}
output, err := finder.FileSystemByID(conn, id)

output, err := conn.DescribeFileSystems(input)
if tfresource.NotFound(err) {
return nil, "", nil
}

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

if output == nil || len(output.FileSystems) == 0 || output.FileSystems[0] == nil {
return nil, "", nil
}

mt := output.FileSystems[0]

return mt, aws.StringValue(mt.LifeCycleState), nil
return output, aws.StringValue(output.LifeCycleState), nil
}
}
2 changes: 0 additions & 2 deletions aws/internal/service/efs/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ func AccessPointDeleted(conn *efs.EFS, accessPointId string) (*efs.AccessPointDe
return nil, err
}

// FileSystemAvailable waits for an Operation to return Available
func FileSystemAvailable(conn *efs.EFS, fileSystemID string) (*efs.FileSystemDescription, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{efs.LifeCycleStateCreating, efs.LifeCycleStateUpdating},
Expand All @@ -78,7 +77,6 @@ func FileSystemAvailable(conn *efs.EFS, fileSystemID string) (*efs.FileSystemDes
return nil, err
}

// FileSystemDeleted waits for an Operation to return Deleted
func FileSystemDeleted(conn *efs.EFS, fileSystemID string) (*efs.FileSystemDescription, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{efs.LifeCycleStateAvailable, efs.LifeCycleStateDeleting},
Expand Down
88 changes: 41 additions & 47 deletions aws/resource_aws_efs_file_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ 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"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/efs/finder"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/efs/waiter"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

func resourceAwsEfsFileSystem() *schema.Resource {
Expand Down Expand Up @@ -112,9 +115,14 @@ func resourceAwsEfsFileSystem() *schema.Resource {
Schema: map[string]*schema.Schema{
"transition_to_ia": {
Type: schema.TypeString,
Required: true,
Optional: true,
ValidateFunc: validation.StringInSlice(efs.TransitionToIARules_Values(), false),
},
"transition_to_primary_storage_class": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(efs.TransitionToPrimaryStorageClassRules_Values(), false),
},
},
},
},
Expand Down Expand Up @@ -188,30 +196,28 @@ func resourceAwsEfsFileSystemCreate(d *schema.ResourceData, meta interface{}) er
return errors.New("encrypted must be set to true when kms_key_id is specified")
}

log.Printf("[DEBUG] EFS file system create options: %#v", *createOpts)
log.Printf("[DEBUG] Creating EFS file system: %s", createOpts)
fs, err := conn.CreateFileSystem(createOpts)

if err != nil {
return fmt.Errorf("Error creating EFS file system: %w", err)
return fmt.Errorf("error creating EFS file system: %w", err)
}

d.SetId(aws.StringValue(fs.FileSystemId))
log.Printf("[INFO] EFS file system ID: %s", d.Id())

if _, err := waiter.FileSystemAvailable(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for EFS file system (%s) to be available: %w", d.Id(), err)
}

log.Printf("[DEBUG] EFS file system %q created.", d.Id())

_, hasLifecyclePolicy := d.GetOk("lifecycle_policy")
if hasLifecyclePolicy {
_, err := conn.PutLifecycleConfiguration(&efs.PutLifecycleConfigurationInput{
FileSystemId: aws.String(d.Id()),
LifecyclePolicies: expandEfsFileSystemLifecyclePolicies(d.Get("lifecycle_policy").([]interface{})),
})

if err != nil {
return fmt.Errorf("Error creating lifecycle policy for EFS file system %q: %s",
d.Id(), err.Error())
return fmt.Errorf("error creating EFS file system (%s) lifecycle configuration: %w", d.Id(), err)
}
}

Expand All @@ -234,6 +240,7 @@ func resourceAwsEfsFileSystemUpdate(d *schema.ResourceData, meta interface{}) er
}

_, err := conn.UpdateFileSystem(input)

if err != nil {
return fmt.Errorf("error updating EFS file system (%s): %w", d.Id(), err)
}
Expand All @@ -257,9 +264,9 @@ func resourceAwsEfsFileSystemUpdate(d *schema.ResourceData, meta interface{}) er
}

_, err := conn.PutLifecycleConfiguration(input)

if err != nil {
return fmt.Errorf("Error updating lifecycle policy for EFS file system %q: %s",
d.Id(), err.Error())
return fmt.Errorf("error updating EFS file system (%s) lifecycle configuration: %w", d.Id(), err)
}
}

Expand All @@ -279,35 +286,18 @@ func resourceAwsEfsFileSystemRead(d *schema.ResourceData, meta interface{}) erro
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

resp, err := conn.DescribeFileSystems(&efs.DescribeFileSystemsInput{
FileSystemId: aws.String(d.Id()),
})
if err != nil {
if isAWSErr(err, efs.ErrCodeFileSystemNotFound, "") {
log.Printf("[WARN] EFS file system (%s) could not be found.", d.Id())
d.SetId("")
return nil
}
return err
}
fs, err := finder.FileSystemByID(conn, d.Id())

if hasEmptyFileSystems(resp) {
return fmt.Errorf("EFS file system %q could not be found.", d.Id())
}

var fs *efs.FileSystemDescription
for _, f := range resp.FileSystems {
if d.Id() == *f.FileSystemId {
fs = f
break
}
}
if fs == nil {
log.Printf("[WARN] EFS File System (%s) not found, removing from state", d.Id())
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] EFS file system (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("error reading EFS file system (%s): %w", d.Id(), err)
}

d.Set("arn", fs.FileSystemArn)
d.Set("availability_zone_id", fs.AvailabilityZoneId)
d.Set("availability_zone_name", fs.AvailabilityZoneName)
Expand Down Expand Up @@ -340,8 +330,9 @@ func resourceAwsEfsFileSystemRead(d *schema.ResourceData, meta interface{}) erro
res, err := conn.DescribeLifecycleConfiguration(&efs.DescribeLifecycleConfigurationInput{
FileSystemId: aws.String(d.Id()),
})

if err != nil {
return fmt.Errorf("Error describing lifecycle configuration for EFS file system (%s): %w", d.Id(), err)
return fmt.Errorf("error reading EFS file system (%s) lifecycle configuration: %w", d.Id(), err)
}

if err := d.Set("lifecycle_policy", flattenEfsFileSystemLifecyclePolicies(res.LifecyclePolicies)); err != nil {
Expand All @@ -358,15 +349,17 @@ func resourceAwsEfsFileSystemDelete(d *schema.ResourceData, meta interface{}) er
_, err := conn.DeleteFileSystem(&efs.DeleteFileSystemInput{
FileSystemId: aws.String(d.Id()),
})

if tfawserr.ErrCodeEquals(err, efs.ErrCodeFileSystemNotFound) {
return nil
}

if err != nil {
if isAWSErr(err, efs.ErrCodeFileSystemNotFound, "") {
return nil
}
return fmt.Errorf("Error delete file system: %s with err %s", d.Id(), err.Error())
return fmt.Errorf("error deleting EFS file system (%s): %w", d.Id(), err)
}

if _, err := waiter.FileSystemDeleted(conn, d.Id()); err != nil {
if isAWSErr(err, efs.ErrCodeFileSystemNotFound, "") {
if tfawserr.ErrCodeEquals(err, efs.ErrCodeFileSystemNotFound) {
return nil
}
return fmt.Errorf("error waiting for EFS file system (%s) deletion: %w", d.Id(), err)
Expand All @@ -375,13 +368,6 @@ func resourceAwsEfsFileSystemDelete(d *schema.ResourceData, meta interface{}) er
return nil
}

func hasEmptyFileSystems(fs *efs.DescribeFileSystemsOutput) bool {
if fs != nil && len(fs.FileSystems) > 0 {
return false
}
return true
}

func flattenEfsFileSystemLifecyclePolicies(apiObjects []*efs.LifecyclePolicy) []interface{} {
var tfList []interface{}

Expand All @@ -396,6 +382,10 @@ func flattenEfsFileSystemLifecyclePolicies(apiObjects []*efs.LifecyclePolicy) []
tfMap["transition_to_ia"] = aws.StringValue(apiObject.TransitionToIA)
}

if apiObject.TransitionToPrimaryStorageClass != nil {
tfMap["transition_to_primary_storage_class"] = aws.StringValue(apiObject.TransitionToPrimaryStorageClass)
}

tfList = append(tfList, tfMap)
}

Expand All @@ -418,6 +408,10 @@ func expandEfsFileSystemLifecyclePolicies(tfList []interface{}) []*efs.Lifecycle
apiObject.TransitionToIA = aws.String(v)
}

if v, ok := tfMap["transition_to_primary_storage_class"].(string); ok && v != "" {
apiObject.TransitionToPrimaryStorageClass = aws.String(v)
}

apiObjects = append(apiObjects, apiObject)
}

Expand Down
Loading

0 comments on commit 9b0205d

Please sign in to comment.