diff --git a/aws/resource_aws_storagegateway_nfs_file_share.go b/aws/resource_aws_storagegateway_nfs_file_share.go index 5a7c8382531..6c7d13c15b5 100644 --- a/aws/resource_aws_storagegateway_nfs_file_share.go +++ b/aws/resource_aws_storagegateway_nfs_file_share.go @@ -48,6 +48,7 @@ func resourceAwsStorageGatewayNfsFileShare() *schema.Resource { "S3_ONEZONE_IA", "S3_STANDARD_IA", "S3_STANDARD", + "S3_INTELLIGENT_TIERING", }, false), }, "fileshare_id": { @@ -112,19 +113,25 @@ func resourceAwsStorageGatewayNfsFileShare() *schema.Resource { }, }, }, - "object_acl": { - Type: schema.TypeString, + "cache_attributes": { + Type: schema.TypeList, Optional: true, - Default: storagegateway.ObjectACLPrivate, - ValidateFunc: validation.StringInSlice([]string{ - storagegateway.ObjectACLAuthenticatedRead, - storagegateway.ObjectACLAwsExecRead, - storagegateway.ObjectACLBucketOwnerFullControl, - storagegateway.ObjectACLBucketOwnerRead, - storagegateway.ObjectACLPrivate, - storagegateway.ObjectACLPublicRead, - storagegateway.ObjectACLPublicReadWrite, - }, false), + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cache_stale_timeout_in_seconds": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(300, 2592000), + }, + }, + }, + }, + "object_acl": { + Type: schema.TypeString, + Optional: true, + Default: storagegateway.ObjectACLPrivate, + ValidateFunc: validation.StringInSlice(storagegateway.ObjectACL_Values(), false), }, "path": { Type: schema.TypeString, @@ -185,10 +192,14 @@ func resourceAwsStorageGatewayNfsFileShareCreate(d *schema.ResourceData, meta in input.KMSKey = aws.String(v.(string)) } + if v, ok := d.GetOk("cache_attributes"); ok { + input.CacheAttributes = expandStorageGatewayNfsFileShareCacheAttributes(v.([]interface{})) + } + log.Printf("[DEBUG] Creating Storage Gateway NFS File Share: %s", input) output, err := conn.CreateNFSFileShare(input) if err != nil { - return fmt.Errorf("error creating Storage Gateway NFS File Share: %s", err) + return fmt.Errorf("error creating Storage Gateway NFS File Share: %w", err) } d.SetId(aws.StringValue(output.FileShareARN)) @@ -203,7 +214,7 @@ func resourceAwsStorageGatewayNfsFileShareCreate(d *schema.ResourceData, meta in } _, err = stateConf.WaitForState() if err != nil { - return fmt.Errorf("error waiting for Storage Gateway NFS File Share creation: %s", err) + return fmt.Errorf("error waiting for Storage Gateway NFS File Share creation: %w", err) } return resourceAwsStorageGatewayNfsFileShareRead(d, meta) @@ -225,7 +236,7 @@ func resourceAwsStorageGatewayNfsFileShareRead(d *schema.ResourceData, meta inte d.SetId("") return nil } - return fmt.Errorf("error reading Storage Gateway NFS File Share: %s", err) + return fmt.Errorf("error reading Storage Gateway NFS File Share: %w", err) } if output == nil || len(output.NFSFileShareInfoList) == 0 || output.NFSFileShareInfoList[0] == nil { @@ -239,8 +250,8 @@ func resourceAwsStorageGatewayNfsFileShareRead(d *schema.ResourceData, meta inte arn := fileshare.FileShareARN d.Set("arn", arn) - if err := d.Set("client_list", schema.NewSet(schema.HashString, flattenStringList(fileshare.ClientList))); err != nil { - return fmt.Errorf("error setting client_list: %s", err) + if err := d.Set("client_list", flattenStringSet(fileshare.ClientList)); err != nil { + return fmt.Errorf("error setting client_list: %w", err) } d.Set("default_storage_class", fileshare.DefaultStorageClass) @@ -252,7 +263,11 @@ func resourceAwsStorageGatewayNfsFileShareRead(d *schema.ResourceData, meta inte d.Set("location_arn", fileshare.LocationARN) if err := d.Set("nfs_file_share_defaults", flattenStorageGatewayNfsFileShareDefaults(fileshare.NFSFileShareDefaults)); err != nil { - return fmt.Errorf("error setting nfs_file_share_defaults: %s", err) + return fmt.Errorf("error setting nfs_file_share_defaults: %w", err) + } + + if err := d.Set("cache_attributes", flattenStorageGatewayNfsFileShareCacheAttributes(fileshare.CacheAttributes)); err != nil { + return fmt.Errorf("error setting cache_attributes: %w", err) } d.Set("object_acl", fileshare.ObjectACL) @@ -263,7 +278,7 @@ func resourceAwsStorageGatewayNfsFileShareRead(d *schema.ResourceData, meta inte d.Set("squash", fileshare.Squash) if err := d.Set("tags", keyvaluetags.StoragegatewayKeyValueTags(fileshare.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %s", err) + return fmt.Errorf("error setting tags: %w", err) } return nil @@ -275,12 +290,13 @@ func resourceAwsStorageGatewayNfsFileShareUpdate(d *schema.ResourceData, meta in if d.HasChange("tags") { o, n := d.GetChange("tags") if err := keyvaluetags.StoragegatewayUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { - return fmt.Errorf("error updating tags: %s", err) + return fmt.Errorf("error updating tags: %w", err) } } if d.HasChanges("client_list", "default_storage_class", "guess_mime_type_enabled", "kms_encrypted", - "nfs_file_share_defaults", "object_acl", "read_only", "requester_pays", "squash", "kms_key_arn") { + "nfs_file_share_defaults", "object_acl", "read_only", "requester_pays", "squash", "kms_key_arn", + "cache_attributes") { input := &storagegateway.UpdateNFSFileShareInput{ ClientList: expandStringSet(d.Get("client_list").(*schema.Set)), @@ -299,10 +315,14 @@ func resourceAwsStorageGatewayNfsFileShareUpdate(d *schema.ResourceData, meta in input.KMSKey = aws.String(v.(string)) } + if v, ok := d.GetOk("cache_attributes"); ok { + input.CacheAttributes = expandStorageGatewayNfsFileShareCacheAttributes(v.([]interface{})) + } + log.Printf("[DEBUG] Updating Storage Gateway NFS File Share: %s", input) _, err := conn.UpdateNFSFileShare(input) if err != nil { - return fmt.Errorf("error updating Storage Gateway NFS File Share: %s", err) + return fmt.Errorf("error updating Storage Gateway NFS File Share: %w", err) } stateConf := &resource.StateChangeConf{ @@ -315,7 +335,7 @@ func resourceAwsStorageGatewayNfsFileShareUpdate(d *schema.ResourceData, meta in } _, err = stateConf.WaitForState() if err != nil { - return fmt.Errorf("error waiting for Storage Gateway NFS File Share update: %s", err) + return fmt.Errorf("error waiting for Storage Gateway NFS File Share update: %w", err) } } @@ -335,7 +355,7 @@ func resourceAwsStorageGatewayNfsFileShareDelete(d *schema.ResourceData, meta in if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") { return nil } - return fmt.Errorf("error deleting Storage Gateway NFS File Share: %s", err) + return fmt.Errorf("error deleting Storage Gateway NFS File Share: %w", err) } stateConf := &resource.StateChangeConf{ @@ -352,7 +372,7 @@ func resourceAwsStorageGatewayNfsFileShareDelete(d *schema.ResourceData, meta in if isResourceNotFoundError(err) { return nil } - return fmt.Errorf("error waiting for Storage Gateway NFS File Share deletion: %s", err) + return fmt.Errorf("error waiting for Storage Gateway NFS File Share deletion: %w", err) } return nil @@ -370,7 +390,7 @@ func storageGatewayNfsFileShareRefreshFunc(fileShareArn string, conn *storagegat if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") { return nil, "MISSING", nil } - return nil, "ERROR", fmt.Errorf("error reading Storage Gateway NFS File Share: %s", err) + return nil, "ERROR", fmt.Errorf("error reading Storage Gateway NFS File Share: %w", err) } if output == nil || len(output.NFSFileShareInfoList) == 0 || output.NFSFileShareInfoList[0] == nil { @@ -414,3 +434,29 @@ func flattenStorageGatewayNfsFileShareDefaults(nfsFileShareDefaults *storagegate return []interface{}{m} } + +func expandStorageGatewayNfsFileShareCacheAttributes(l []interface{}) *storagegateway.CacheAttributes { + if len(l) == 0 || l[0] == nil { + return nil + } + + m := l[0].(map[string]interface{}) + + ca := &storagegateway.CacheAttributes{ + CacheStaleTimeoutInSeconds: aws.Int64(int64(m["cache_stale_timeout_in_seconds"].(int))), + } + + return ca +} + +func flattenStorageGatewayNfsFileShareCacheAttributes(ca *storagegateway.CacheAttributes) []interface{} { + if ca == nil { + return []interface{}{} + } + + m := map[string]interface{}{ + "cache_stale_timeout_in_seconds": aws.Int64Value(ca.CacheStaleTimeoutInSeconds), + } + + return []interface{}{m} +} diff --git a/aws/resource_aws_storagegateway_nfs_file_share_test.go b/aws/resource_aws_storagegateway_nfs_file_share_test.go index ea5d21f90e6..81ebfc1d92e 100644 --- a/aws/resource_aws_storagegateway_nfs_file_share_test.go +++ b/aws/resource_aws_storagegateway_nfs_file_share_test.go @@ -47,6 +47,7 @@ func TestAccAWSStorageGatewayNfsFileShare_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "requester_pays", "false"), resource.TestCheckResourceAttrPair(resourceName, "role_arn", iamResourceName, "arn"), resource.TestCheckResourceAttr(resourceName, "squash", "RootSquash"), + resource.TestCheckResourceAttr(resourceName, "cache_attributes.#", "0"), ), }, { @@ -458,6 +459,71 @@ func TestAccAWSStorageGatewayNfsFileShare_Squash(t *testing.T) { }) } +func TestAccAWSStorageGatewayNfsFileShare_cacheAttributes(t *testing.T) { + var nfsFileShare storagegateway.NFSFileShareInfo + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_nfs_file_share.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayNfsFileShareDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayNfsFileShareConfigCacheAttributes(rName, 300), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayNfsFileShareExists(resourceName, &nfsFileShare), + resource.TestCheckResourceAttr(resourceName, "cache_attributes.#", "1"), + resource.TestCheckResourceAttr(resourceName, "cache_attributes.0.cache_stale_timeout_in_seconds", "300"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSStorageGatewayNfsFileShareConfigCacheAttributes(rName, 500), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayNfsFileShareExists(resourceName, &nfsFileShare), + resource.TestCheckResourceAttr(resourceName, "cache_attributes.#", "1"), + resource.TestCheckResourceAttr(resourceName, "cache_attributes.0.cache_stale_timeout_in_seconds", "500"), + ), + }, + { + Config: testAccAWSStorageGatewayNfsFileShareConfigCacheAttributes(rName, 300), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayNfsFileShareExists(resourceName, &nfsFileShare), + resource.TestCheckResourceAttr(resourceName, "cache_attributes.#", "1"), + resource.TestCheckResourceAttr(resourceName, "cache_attributes.0.cache_stale_timeout_in_seconds", "300"), + ), + }, + }, + }) +} + +func TestAccAWSStorageGatewayNfsFileShare_disappears(t *testing.T) { + var nfsFileShare storagegateway.NFSFileShareInfo + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_nfs_file_share.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayNfsFileShareDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayNfsFileShareConfig_Required(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayNfsFileShareExists(resourceName, &nfsFileShare), + testAccCheckResourceDisappears(testAccProvider, resourceAwsStorageGatewayNfsFileShare(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckAWSStorageGatewayNfsFileShareDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).storagegatewayconn @@ -783,3 +849,18 @@ resource "aws_storagegateway_nfs_file_share" "test" { } `, squash) } + +func testAccAWSStorageGatewayNfsFileShareConfigCacheAttributes(rName string, timeout int) string { + return testAccAWSStorageGateway_S3FileShareBase(rName) + fmt.Sprintf(` +resource "aws_storagegateway_nfs_file_share" "test" { + client_list = ["0.0.0.0/0"] + gateway_arn = aws_storagegateway_gateway.test.arn + location_arn = aws_s3_bucket.test.arn + role_arn = aws_iam_role.test.arn + + cache_attributes { + cache_stale_timeout_in_seconds = %[1]d + } +} +`, timeout) +} diff --git a/website/docs/r/storagegateway_nfs_file_share.html.markdown b/website/docs/r/storagegateway_nfs_file_share.html.markdown index a553de6a896..2381d5f4e63 100644 --- a/website/docs/r/storagegateway_nfs_file_share.html.markdown +++ b/website/docs/r/storagegateway_nfs_file_share.html.markdown @@ -33,7 +33,8 @@ The following arguments are supported: * `guess_mime_type_enabled` - (Optional) Boolean value that enables guessing of the MIME type for uploaded objects based on file extensions. Defaults to `true`. * `kms_encrypted` - (Optional) Boolean value if `true` to use Amazon S3 server side encryption with your own AWS KMS key, or `false` to use a key managed by Amazon S3. Defaults to `false`. * `kms_key_arn` - (Optional) Amazon Resource Name (ARN) for KMS key used for Amazon S3 server side encryption. This value can only be set when `kms_encrypted` is true. -* `nfs_file_share_defaults` - (Optional) Nested argument with file share default values. More information below. +* `nfs_file_share_defaults` - (Optional) Nested argument with file share default values. More information below. see [NFS File Share Defaults](#nfs_file_share_defaults) for more details. +* `cache_attributes` - (Optional) Refresh cache information. see [Cache Attributes](#cache_attributes) for more details. * `object_acl` - (Optional) Access Control List permission for S3 bucket objects. Defaults to `private`. * `read_only` - (Optional) Boolean to indicate write status of file share. File share does not accept writes if `true`. Defaults to `false`. * `requester_pays` - (Optional) Boolean who pays the cost of the request and the data download from the Amazon S3 bucket. Set this value to `true` if you want the requester to pay instead of the bucket owner. Defaults to `false`. @@ -49,6 +50,13 @@ Files and folders stored as Amazon S3 objects in S3 buckets don't, by default, h * `group_id` - (Optional) The default group ID for the file share (unless the files have another group ID specified). Defaults to `65534` (`nfsnobody`). Valid values: `0` through `4294967294`. * `owner_id` - (Optional) The default owner ID for the file share (unless the files have another owner ID specified). Defaults to `65534` (`nfsnobody`). Valid values: `0` through `4294967294`. +### cache_attributes + +* `cache_stale_timeout_in_seconds` - (Optional) Refreshes a file share's cache by using Time To Live (TTL). + TTL is the length of time since the last refresh after which access to the directory would cause the file gateway + to first refresh that directory's contents from the Amazon S3 bucket. Valid Values: 300 to 2,592,000 seconds (5 minutes to 30 days) + + ## Attribute Reference In addition to all arguments above, the following attributes are exported: