Skip to content

Commit

Permalink
adding efs_file_system lifecycle_policy config block
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Kennedy committed Aug 6, 2019
1 parent f780586 commit 3a5475f
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 1 deletion.
89 changes: 89 additions & 0 deletions aws/resource_aws_efs_file_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func resourceAwsEfsFileSystem() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},

"creation_token": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -93,6 +94,26 @@ func resourceAwsEfsFileSystem() *schema.Resource {
efs.ThroughputModeProvisioned,
}, false),
},

"lifecycle_policy": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"transition_to_ia": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
efs.TransitionToIARulesAfter14Days,
efs.TransitionToIARulesAfter30Days,
efs.TransitionToIARulesAfter60Days,
efs.TransitionToIARulesAfter90Days,
}, false),
},
},
},
},
},
}
}
Expand Down Expand Up @@ -160,6 +181,18 @@ func resourceAwsEfsFileSystemCreate(d *schema.ResourceData, meta interface{}) er
}
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: resourceAwsEfsFileSystemLifecyclePolicy(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())
}
}

err = setTagsEFS(conn, d)
if err != nil {
return fmt.Errorf("error setting tags for EFS file system (%q): %s", d.Id(), err)
Expand Down Expand Up @@ -203,6 +236,17 @@ func resourceAwsEfsFileSystemUpdate(d *schema.ResourceData, meta interface{}) er
}
}

if d.HasChange("lifecycle_policy") {
_, err := conn.PutLifecycleConfiguration(&efs.PutLifecycleConfigurationInput{
FileSystemId: aws.String(d.Id()),
LifecyclePolicies: resourceAwsEfsFileSystemLifecyclePolicy(d.Get("lifecycle_policy").([]interface{})),
})
if err != nil {
return fmt.Errorf("Error updating lifecycle policy for EFS file system %q: %s",
d.Id(), err.Error())
}
}

if d.HasChange("tags") {
err := setTagsEFS(conn, d)
if err != nil {
Expand Down Expand Up @@ -297,6 +341,17 @@ func resourceAwsEfsFileSystemRead(d *schema.ResourceData, meta interface{}) erro
return fmt.Errorf("error setting dns_name: %s", err)
}

res, err := conn.DescribeLifecycleConfiguration(&efs.DescribeLifecycleConfigurationInput{
FileSystemId: fs.FileSystemId,
})
if err != nil {
return fmt.Errorf("Error describing lifecycle configuration for EFS file system (%s): %s",
aws.StringValue(fs.FileSystemId), err)
}
if err := resourceAwsEfsFileSystemSetLifecyclePolicy(d, res.LifecyclePolicies); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -379,3 +434,37 @@ func resourceEfsFileSystemCreateUpdateRefreshFunc(id string, conn *efs.EFS) reso
return fs, state, nil
}
}

func resourceAwsEfsFileSystemSetLifecyclePolicy(d *schema.ResourceData, lp []*efs.LifecyclePolicy) error {
log.Printf("[DEBUG] lifecycle pols: %s %d", lp, len(lp))
if len(lp) == 0 {
d.Set("lifecycle_policy", nil)
return nil
}
newLP := make([]*map[string]interface{}, len(lp))

for i := 0; i < len(lp); i++ {
config := lp[i]
data := make(map[string]interface{})
newLP[i] = &data
if config.TransitionToIA != nil {
data["transition_to_ia"] = *config.TransitionToIA
}
log.Printf("[DEBUG] lp: %s", data)
}

if err := d.Set("lifecycle_policy", newLP); err != nil {
return fmt.Errorf("error setting lifecycle_policy: %s", err)
}
return nil
}

func resourceAwsEfsFileSystemLifecyclePolicy(lcPol []interface{}) []*efs.LifecyclePolicy {
result := make([]*efs.LifecyclePolicy, len(lcPol))

for i := 0; i < len(lcPol); i++ {
lp := lcPol[i].(map[string]interface{})
result[i] = &efs.LifecyclePolicy{TransitionToIA: aws.String(lp["transition_to_ia"].(string))}
}
return result
}
176 changes: 175 additions & 1 deletion aws/resource_aws_efs_file_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func TestAccAWSEFSFileSystem_importBasic(t *testing.T) {
{
Config: testAccAWSEFSFileSystemConfigWithTags(rInt),
},

{
ResourceName: resourceName,
ImportState: true,
Expand Down Expand Up @@ -261,6 +260,123 @@ func TestAccAWSEFSFileSystem_ThroughputMode(t *testing.T) {
})
}

func TestAccAWSEFSFileSystem_lifecyclePolicy(t *testing.T) {
resourceName := "aws_efs_file_system.foo-with-lifecycle-policy"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckEfsFileSystemDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEFSFileSystemConfigWithLifecyclePolicy(
"transition_to_ia",
"invalid_value",
),
ExpectError: regexp.MustCompile(`got invalid_value`),
},
{
Config: testAccAWSEFSFileSystemConfigWithLifecyclePolicy(
"transition_to_ia",
efs.TransitionToIARulesAfter30Days,
),
Check: resource.ComposeTestCheckFunc(
testAccCheckEfsFileSystem(resourceName),
testAccCheckEfsFileSystemLifecyclePolicy(resourceName, "badExpectation"),
),
ExpectError: regexp.MustCompile(`Expected: badExpectation`),
},
{
Config: testAccAWSEFSFileSystemConfigWithLifecyclePolicy(
"transition_to_ia",
efs.TransitionToIARulesAfter30Days,
),
Check: resource.ComposeTestCheckFunc(
testAccCheckEfsFileSystem(resourceName),
testAccCheckEfsFileSystemLifecyclePolicy(resourceName, efs.TransitionToIARulesAfter30Days),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSEFSFileSystem_lifecyclePolicy_update(t *testing.T) {
resourceName := "aws_efs_file_system.foo-with-lifecycle-policy"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckEfsFileSystemDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEFSFileSystemConfigWithLifecyclePolicy(
"transition_to_ia",
efs.TransitionToIARulesAfter30Days,
),
Check: resource.ComposeTestCheckFunc(
testAccCheckEfsFileSystem(resourceName),
testAccCheckEfsFileSystemLifecyclePolicy(resourceName, efs.TransitionToIARulesAfter30Days),
),
},
{
Config: testAccAWSEFSFileSystemConfigWithLifecyclePolicy(
"transition_to_ia",
efs.TransitionToIARulesAfter90Days,
),
Check: resource.ComposeTestCheckFunc(
testAccCheckEfsFileSystem(resourceName),
testAccCheckEfsFileSystemLifecyclePolicy(resourceName, efs.TransitionToIARulesAfter90Days),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSEFSFileSystem_lifecyclePolicy_removal(t *testing.T) {
resourceName := "aws_efs_file_system.foo-with-lifecycle-policy"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckEfsFileSystemDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEFSFileSystemConfigWithLifecyclePolicy(
"transition_to_ia",
efs.TransitionToIARulesAfter14Days,
),
Check: resource.ComposeTestCheckFunc(
testAccCheckEfsFileSystem(resourceName),
testAccCheckEfsFileSystemLifecyclePolicy(resourceName, efs.TransitionToIARulesAfter14Days),
),
},
{
Config: testAccAWSEFSFileSystemConfigRemovedLifecyclePolicy,
Check: resource.ComposeTestCheckFunc(
testAccCheckEfsFileSystem(resourceName),
testAccCheckEfsFileSystemLifecyclePolicy(resourceName, efs.TransitionToIARulesAfter14Days),
),
ExpectError: regexp.MustCompile(fmt.Sprintf(`Expected: %s`, efs.TransitionToIARulesAfter14Days)),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckEfsFileSystemDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).efsconn
for _, rs := range s.RootModule().Resources {
Expand Down Expand Up @@ -391,6 +507,50 @@ func testAccCheckEfsFileSystemPerformanceMode(resourceID string, expectedMode st
}
}

func testAccCheckEfsFileSystemLifecyclePolicy(resourceID string, expectedVal string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceID]
if !ok {
return fmt.Errorf("Not found: %s", resourceID)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

conn := testAccProvider.Meta().(*AWSClient).efsconn
resp, err := conn.DescribeFileSystems(&efs.DescribeFileSystemsInput{
FileSystemId: aws.String(rs.Primary.ID),
})
if err != nil {
return fmt.Errorf("Error describing EFS file systems: %s", err.Error())
}

fs := resp.FileSystems[0]

res, err := conn.DescribeLifecycleConfiguration(&efs.DescribeLifecycleConfigurationInput{
FileSystemId: fs.FileSystemId,
})
if err != nil {
return fmt.Errorf("Error describing lifecycle policy for EFS file system (%s): %s",
aws.StringValue(fs.FileSystemId), err.Error())
}
lp := res.LifecyclePolicies

newLP := make([]*map[string]interface{}, len(lp))

for i := 0; i < len(lp); i++ {
config := lp[i]
data := make(map[string]interface{})
newLP[i] = &data
if *config.TransitionToIA == expectedVal {
return nil
}
}
return fmt.Errorf("Lifecycle Policy mismatch.\nExpected: %s\nFound: %+v", expectedVal, lp)
}
}

const testAccAWSEFSFileSystemConfig = `
resource "aws_efs_file_system" "foo" {
creation_token = "radeksimko"
Expand Down Expand Up @@ -477,3 +637,17 @@ resource "aws_efs_file_system" "test" {
}
`, provisionedThroughputInMibps)
}

func testAccAWSEFSFileSystemConfigWithLifecyclePolicy(lpName string, lpVal string) string {
return fmt.Sprintf(`
resource "aws_efs_file_system" "foo-with-lifecycle-policy" {
lifecycle_policy {
%s = %q
}
}
`, lpName, lpVal)
}

const testAccAWSEFSFileSystemConfigRemovedLifecyclePolicy = `
resource "aws_efs_file_system" "foo-with-lifecycle-policy" {}
`
20 changes: 20 additions & 0 deletions website/docs/r/efs_file_system.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Provides an Elastic File System (EFS) resource.

## Example Usage

### EFS File System w/ tags

```hcl
resource "aws_efs_file_system" "foo" {
creation_token = "my-product"
Expand All @@ -22,6 +24,18 @@ resource "aws_efs_file_system" "foo" {
}
```

### Using lifecycle policy

```hcl
resource "aws_efs_file_system" "foo_with_lifecyle_policy" {
creation_token = "my-product"
lifecycle_policy {
transition_to_ia = "AFTER_30_DAYS"
}
}
```

## Argument Reference

The following arguments are supported:
Expand All @@ -32,11 +46,17 @@ system creation. By default generated by Terraform. See [Elastic File System]
(http://docs.aws.amazon.com/efs/latest/ug/) user guide for more information.
* `encrypted` - (Optional) If true, the disk will be encrypted.
* `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying kms_key_id, encrypted needs to be set to true.
* `lifecycle_policy` - (Optional) A file system [lifecycle policy](https://docs.aws.amazon.com/efs/latest/ug/API_LifecyclePolicy.html) object (documented below).
* `performance_mode` - (Optional) The file system performance mode. Can be either `"generalPurpose"` or `"maxIO"` (Default: `"generalPurpose"`).
* `provisioned_throughput_in_mibps` - (Optional) The throughput, measured in MiB/s, that you want to provision for the file system. Only applicable with `throughput_mode` set to `provisioned`.
* `tags` - (Optional) A mapping of tags to assign to the file system.
* `throughput_mode` - (Optional) Throughput mode for the file system. Defaults to `bursting`. Valid values: `bursting`, `provisioned`. When using `provisioned`, also set `provisioned_throughput_in_mibps`.

### Lifecycle Policy Arguments
For **lifecycle_policy** the following attributes are supported:

* `transition_to_ia` - (Optional) Indicates how long it takes to transition files to the IA storage class. Valid values: `AFTER_14_DAYS`, `AFTER_30_DAYS`, `AFTER_60_DAYS`, or `AFTER_90_DAYS`.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:
Expand Down

0 comments on commit 3a5475f

Please sign in to comment.