From 29c9c07794de1b3dd7edc6ac00014ee6f31bb122 Mon Sep 17 00:00:00 2001 From: surajsubramanian Date: Wed, 6 Mar 2024 02:22:30 +0200 Subject: [PATCH 01/13] [cloudfront/function] Add key_value_store_associations set --- internal/service/cloudfront/function.go | 52 ++++++++++++++++++ .../cloudfront/function_data_source.go | 12 +++++ .../cloudfront/function_data_source_test.go | 15 ++++-- internal/service/cloudfront/function_test.go | 54 +++++++++++++++++++ .../docs/r/cloudfront_function.html.markdown | 1 + 5 files changed, 130 insertions(+), 4 deletions(-) diff --git a/internal/service/cloudfront/function.go b/internal/service/cloudfront/function.go index c9ec3475dfb..4bc4396a0e1 100644 --- a/internal/service/cloudfront/function.go +++ b/internal/service/cloudfront/function.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" ) // @SDKResource("aws_cloudfront_function") @@ -69,6 +70,15 @@ func ResourceFunction() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "key_value_store_associations": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + // Required: true, + ValidateFunc: verify.ValidARN, + }, + }, }, } } @@ -87,6 +97,10 @@ func resourceFunctionCreate(ctx context.Context, d *schema.ResourceData, meta in Name: aws.String(functionName), } + if v, ok := d.GetOk("key_value_store_associations"); ok { + input.FunctionConfig.KeyValueStoreAssociations = expandKeyValueStoreAssociations(v.(*schema.Set).List()) + } + log.Printf("[DEBUG] Creating CloudFront Function: %s", functionName) output, err := conn.CreateFunctionWithContext(ctx, input) @@ -147,6 +161,10 @@ func resourceFunctionRead(ctx context.Context, d *schema.ResourceData, meta inte d.Set("code", string(getFunctionOutput.FunctionCode)) + if err := d.Set("key_value_store_associations", flattenKeyValueStoreAssociations(describeFunctionOutput.FunctionSummary.FunctionConfig.KeyValueStoreAssociations)); err != nil { + return sdkdiag.AppendErrorf(diags, "reading CloudFront Function (%s) DEVELOPMENT stage code: %s", d.Id(), err) + } + describeFunctionOutput, err = FindFunctionByNameAndStage(ctx, conn, d.Id(), cloudfront.FunctionStageLive) if tfresource.NotFound(err) { @@ -223,3 +241,37 @@ func resourceFunctionDelete(ctx context.Context, d *schema.ResourceData, meta in return diags } + +func expandKeyValueStoreAssociations(tfList []interface{}) *cloudfront.KeyValueStoreAssociations { + if len(tfList) == 0 { + return nil + } + + var items []*cloudfront.KeyValueStoreAssociation + + for _, tfItem := range tfList { + item := tfItem.(string) + + items = append(items, &cloudfront.KeyValueStoreAssociation{ + KeyValueStoreARN: aws.String(item), + }) + } + + return &cloudfront.KeyValueStoreAssociations{ + Items: items, + Quantity: aws.Int64(int64(len(items))), + } +} + +func flattenKeyValueStoreAssociations(input *cloudfront.KeyValueStoreAssociations) []string { + if input == nil { + return nil + } + + var items []string + + for _, item := range input.Items { + items = append(items, aws.StringValue(item.KeyValueStoreARN)) + } + return items +} diff --git a/internal/service/cloudfront/function_data_source.go b/internal/service/cloudfront/function_data_source.go index 5cfa12a638f..730a8098dc1 100644 --- a/internal/service/cloudfront/function_data_source.go +++ b/internal/service/cloudfront/function_data_source.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/verify" ) // @SDKDataSource("aws_cloudfront_function") @@ -67,6 +68,15 @@ func DataSourceFunction() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "key_value_store_associations": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + // Required: true, + ValidateFunc: verify.ValidARN, + }, + }, }, } } @@ -97,6 +107,8 @@ func dataSourceFunctionRead(ctx context.Context, d *schema.ResourceData, meta in Stage: aws.String(stage), }) + d.Set("key_value_store_associations", flattenKeyValueStoreAssociations(describeFunctionOutput.FunctionSummary.FunctionConfig.KeyValueStoreAssociations)) + if err != nil { return sdkdiag.AppendErrorf(diags, "getting CloudFront Function (%s): %s", d.Id(), err) } diff --git a/internal/service/cloudfront/function_data_source_test.go b/internal/service/cloudfront/function_data_source_test.go index cdec47c8cc2..b60feb72d87 100644 --- a/internal/service/cloudfront/function_data_source_test.go +++ b/internal/service/cloudfront/function_data_source_test.go @@ -19,6 +19,7 @@ func TestAccCloudFrontFunctionDataSource_basic(t *testing.T) { rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) dataSourceName := "data.aws_cloudfront_function.test" resourceName := "aws_cloudfront_function.test" + keyValueStorerName := "aws_cloudfront_key_value_store.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, cloudfront.EndpointsID) }, @@ -36,6 +37,7 @@ func TestAccCloudFrontFunctionDataSource_basic(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"), resource.TestCheckResourceAttrPair(dataSourceName, "runtime", resourceName, "runtime"), resource.TestCheckResourceAttrPair(dataSourceName, "status", resourceName, "status"), + resource.TestCheckResourceAttrPair(dataSourceName, "key_value_store_associations.0", keyValueStorerName, "arn"), ), }, }, @@ -45,10 +47,11 @@ func TestAccCloudFrontFunctionDataSource_basic(t *testing.T) { func testAccFunctionDataSourceConfig_basic(rName string) string { return fmt.Sprintf(` resource "aws_cloudfront_function" "test" { - name = %[1]q - runtime = "cloudfront-js-1.0" - comment = "test" - code = <<-EOT + name = %[1]q + runtime = "cloudfront-js-2.0" + comment = "test" + key_value_store_associations = [aws_cloudfront_key_value_store.test.arn] + code = <<-EOT function handler(event) { var response = { statusCode: 302, @@ -63,6 +66,10 @@ function handler(event) { EOT } +resource "aws_cloudfront_key_value_store" "test" { + name = %[1]q +} + data "aws_cloudfront_function" "test" { name = aws_cloudfront_function.test.name stage = "LIVE" diff --git a/internal/service/cloudfront/function_test.go b/internal/service/cloudfront/function_test.go index 72f9ebe13e2..2feac9cf558 100644 --- a/internal/service/cloudfront/function_test.go +++ b/internal/service/cloudfront/function_test.go @@ -290,6 +290,35 @@ func TestAccCloudFrontFunction_Update_comment(t *testing.T) { }) } +func TestAccCloudFrontFunction_KeyValueStoreAssociations(t *testing.T) { + ctx := acctest.Context(t) + var conf cloudfront.DescribeFunctionOutput + resourceName := "aws_cloudfront_function.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, cloudfront.EndpointsID) }, + ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckFunctionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccFunctionConfig_KeyValueStoreAssociation(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckFunctionExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttrPair(resourceName, "key_value_store_associations.0", "aws_cloudfront_key_value_store.test", "arn"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"publish"}, + }, + }, + }) +} + func testAccCheckFunctionDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).CloudFrontConn(ctx) @@ -577,3 +606,28 @@ EOT } `, rName, comment) } + +func testAccFunctionConfig_KeyValueStoreAssociation(rName string) string { + return acctest.ConfigCompose( + testAccKeyValueStoreConfig_basic(rName), + fmt.Sprintf(` +resource "aws_cloudfront_function" "test" { + name = %[1]q + runtime = "cloudfront-js-2.0" + key_value_store_associations = [aws_cloudfront_key_value_store.test.arn] + code = <<-EOT +function handler(event) { + var response = { + statusCode: 302, + statusDescription: 'Found', + headers: { + 'cloudfront-functions': { value: 'generated-by-CloudFront-Functions' }, + 'location': { value: 'https://aws.amazon.com/cloudfront/' } + } + }; + return response; +} +EOT +} +`, rName)) +} diff --git a/website/docs/r/cloudfront_function.html.markdown b/website/docs/r/cloudfront_function.html.markdown index df52b5627c6..b6efb088dbd 100644 --- a/website/docs/r/cloudfront_function.html.markdown +++ b/website/docs/r/cloudfront_function.html.markdown @@ -40,6 +40,7 @@ The following arguments are optional: * `comment` - (Optional) Comment. * `publish` - (Optional) Whether to publish creation/change as Live CloudFront Function Version. Defaults to `true`. +* `key_value_store_associations` - (Optional) List of `aws_cloudfront_key_value_store` ARNs to be associated to the function. ## Attribute Reference From 1a6b25e1f5bdb225a3f407fa97afb069a61b92c1 Mon Sep 17 00:00:00 2001 From: surajsubramanian Date: Wed, 6 Mar 2024 02:48:46 +0200 Subject: [PATCH 02/13] Add changelog --- .changelog/36228.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/36228.txt diff --git a/.changelog/36228.txt b/.changelog/36228.txt new file mode 100644 index 00000000000..7320a52b1d3 --- /dev/null +++ b/.changelog/36228.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_cloudfront_function: Add `key_value_store_associations` argument +``` From bbc3359db4705e0107389054d984c1829a3e1c1a Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:01:15 -0400 Subject: [PATCH 03/13] cloudfront: Amend function, enable kvs association on update, set max associations --- internal/service/cloudfront/function.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/internal/service/cloudfront/function.go b/internal/service/cloudfront/function.go index 4bc4396a0e1..967b48bf5f2 100644 --- a/internal/service/cloudfront/function.go +++ b/internal/service/cloudfront/function.go @@ -73,9 +73,10 @@ func ResourceFunction() *schema.Resource { "key_value_store_associations": { Type: schema.TypeSet, Optional: true, + // AWS docs state that only one key value store can be associated with a function at a time. + MaxItems: 1, Elem: &schema.Schema{ - Type: schema.TypeString, - // Required: true, + Type: schema.TypeString, ValidateFunc: verify.ValidARN, }, }, @@ -183,7 +184,7 @@ func resourceFunctionUpdate(ctx context.Context, d *schema.ResourceData, meta in conn := meta.(*conns.AWSClient).CloudFrontConn(ctx) etag := d.Get("etag").(string) - if d.HasChanges("code", "comment", "runtime") { + if d.HasChanges("code", "comment", "runtime", "key_value_store_associations") { input := &cloudfront.UpdateFunctionInput{ FunctionCode: []byte(d.Get("code").(string)), FunctionConfig: &cloudfront.FunctionConfig{ @@ -194,6 +195,10 @@ func resourceFunctionUpdate(ctx context.Context, d *schema.ResourceData, meta in IfMatch: aws.String(etag), } + if v, ok := d.GetOk("key_value_store_associations"); ok { + input.FunctionConfig.KeyValueStoreAssociations = expandKeyValueStoreAssociations(v.(*schema.Set).List()) + } + log.Printf("[INFO] Updating CloudFront Function: %s", d.Id()) output, err := conn.UpdateFunctionWithContext(ctx, input) From bc0d5ae734b126eaa419170dd31be60d4353c122 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:01:50 -0400 Subject: [PATCH 04/13] cloudfront: Amend function_test, Add test case for updating kvs associations --- internal/service/cloudfront/function_test.go | 69 ++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/internal/service/cloudfront/function_test.go b/internal/service/cloudfront/function_test.go index 2feac9cf558..3cbb340451d 100644 --- a/internal/service/cloudfront/function_test.go +++ b/internal/service/cloudfront/function_test.go @@ -315,6 +315,20 @@ func TestAccCloudFrontFunction_KeyValueStoreAssociations(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"publish"}, }, + { + Config: testAccFunctionConfig_KeyValueStoreAssociationCodeUpdate(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckFunctionExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttrPair(resourceName, "key_value_store_associations.0", "aws_cloudfront_key_value_store.test", "arn"), + ), + }, + { + Config: testAccFunctionConfig_KeyValueStoreAssociationUpdate(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckFunctionExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttrPair(resourceName, "key_value_store_associations.0", "aws_cloudfront_key_value_store.test2", "arn"), + ), + }, }, }) } @@ -631,3 +645,58 @@ EOT } `, rName)) } + +func testAccFunctionConfig_KeyValueStoreAssociationCodeUpdate(rName string) string { + return acctest.ConfigCompose( + testAccKeyValueStoreConfig_basic(rName), + fmt.Sprintf(` +resource "aws_cloudfront_function" "test" { + name = %[1]q + runtime = "cloudfront-js-2.0" + key_value_store_associations = [aws_cloudfront_key_value_store.test.arn] + code = <<-EOT +// updated code +function handler(event) { + var response = { + statusCode: 302, + statusDescription: 'Found', + headers: { + 'cloudfront-functions': { value: 'generated-by-CloudFront-Functions' }, + 'location': { value: 'https://aws.amazon.com/cloudfront/' } + } + }; + return response; +} +EOT +} +`, rName)) +} + +func testAccFunctionConfig_KeyValueStoreAssociationUpdate(rName string) string { + return acctest.ConfigCompose( + testAccKeyValueStoreConfig_basic(rName), + fmt.Sprintf(` +resource "aws_cloudfront_key_value_store" "test2" { + name = "%[1]s2" +} +resource "aws_cloudfront_function" "test" { + name = %[1]q + runtime = "cloudfront-js-2.0" + key_value_store_associations = [aws_cloudfront_key_value_store.test2.arn] + code = <<-EOT +// updated code +function handler(event) { + var response = { + statusCode: 302, + statusDescription: 'Found', + headers: { + 'cloudfront-functions': { value: 'generated-by-CloudFront-Functions' }, + 'location': { value: 'https://aws.amazon.com/cloudfront/' } + } + }; + return response; +} +EOT +} +`, rName)) +} From c3b5b3de62aea810c93dda83c94c7ec41c721416 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:03:05 -0400 Subject: [PATCH 05/13] website/r: Amend cloudfront_function, Add limit to description --- website/docs/r/cloudfront_function.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/cloudfront_function.html.markdown b/website/docs/r/cloudfront_function.html.markdown index b6efb088dbd..f51aa9c0383 100644 --- a/website/docs/r/cloudfront_function.html.markdown +++ b/website/docs/r/cloudfront_function.html.markdown @@ -40,7 +40,7 @@ The following arguments are optional: * `comment` - (Optional) Comment. * `publish` - (Optional) Whether to publish creation/change as Live CloudFront Function Version. Defaults to `true`. -* `key_value_store_associations` - (Optional) List of `aws_cloudfront_key_value_store` ARNs to be associated to the function. +* `key_value_store_associations` - (Optional) List of `aws_cloudfront_key_value_store` ARNs to be associated to the function. AWS limits associations to on key value store per function. ## Attribute Reference From 1787347eb53f6fba8c239eb0b5e3784a16e44c87 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:03:38 -0400 Subject: [PATCH 06/13] website/d: Amend cloudfront_function, Add `key_value_store_associations` field description --- website/docs/d/cloudfront_function.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/d/cloudfront_function.html.markdown b/website/docs/d/cloudfront_function.html.markdown index ea91802c5e4..cb08988f54c 100644 --- a/website/docs/d/cloudfront_function.html.markdown +++ b/website/docs/d/cloudfront_function.html.markdown @@ -37,6 +37,8 @@ This data source exports the following attributes in addition to the arguments a * `code` - Source code of the function * `comment` - Comment. * `etag` - ETag hash of the function +* `key_value_store_associations` - List of `aws_cloudfront_key_value_store` ARNs associated to the function. * `last_modified_time` - When this resource was last modified. * `runtime` - Identifier of the function's runtime. * `status` - Status of the function. Can be `UNPUBLISHED`, `UNASSOCIATED` or `ASSOCIATED`. + From 22345753f4dfe5d28117e012bd1eedb3b2ec317f Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:35:25 -0400 Subject: [PATCH 07/13] changelog: Update changelog to new PR number --- .changelog/{36228.txt => 36585.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{36228.txt => 36585.txt} (100%) diff --git a/.changelog/36228.txt b/.changelog/36585.txt similarity index 100% rename from .changelog/36228.txt rename to .changelog/36585.txt From 10a72b6a9b4cdc153363374262f9116ecc1e5da0 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:00:36 -0400 Subject: [PATCH 08/13] website/d: Amend cloudfront_function, website-lint-fix --- website/docs/d/cloudfront_function.html.markdown | 1 - 1 file changed, 1 deletion(-) diff --git a/website/docs/d/cloudfront_function.html.markdown b/website/docs/d/cloudfront_function.html.markdown index cb08988f54c..e57940b47f7 100644 --- a/website/docs/d/cloudfront_function.html.markdown +++ b/website/docs/d/cloudfront_function.html.markdown @@ -41,4 +41,3 @@ This data source exports the following attributes in addition to the arguments a * `last_modified_time` - When this resource was last modified. * `runtime` - Identifier of the function's runtime. * `status` - Status of the function. Can be `UNPUBLISHED`, `UNASSOCIATED` or `ASSOCIATED`. - From c4ccf1e89d4c6c826da4fb5e29f3fe493ea487d7 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:03:58 -0400 Subject: [PATCH 09/13] cloudfront: Amend function, remove MaxItems --- internal/service/cloudfront/function.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/service/cloudfront/function.go b/internal/service/cloudfront/function.go index 967b48bf5f2..7634712fb1c 100644 --- a/internal/service/cloudfront/function.go +++ b/internal/service/cloudfront/function.go @@ -73,8 +73,6 @@ func ResourceFunction() *schema.Resource { "key_value_store_associations": { Type: schema.TypeSet, Optional: true, - // AWS docs state that only one key value store can be associated with a function at a time. - MaxItems: 1, Elem: &schema.Schema{ Type: schema.TypeString, ValidateFunc: verify.ValidARN, From c7ea4d327059bea1ebe29c015f931c2367344774 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:05:20 -0400 Subject: [PATCH 10/13] cloudfront: Amend function_data_source, remove comment --- internal/service/cloudfront/function_data_source.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/service/cloudfront/function_data_source.go b/internal/service/cloudfront/function_data_source.go index 730a8098dc1..639d2907ca9 100644 --- a/internal/service/cloudfront/function_data_source.go +++ b/internal/service/cloudfront/function_data_source.go @@ -72,8 +72,7 @@ func DataSourceFunction() *schema.Resource { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, - // Required: true, + Type: schema.TypeString, ValidateFunc: verify.ValidARN, }, }, From c5d5a154bba022e29437740d5c64764f9ccc09ff Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Mar 2024 07:57:28 -0400 Subject: [PATCH 11/13] Additional CHANGELOG entry. --- .changelog/36585.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.changelog/36585.txt b/.changelog/36585.txt index 7320a52b1d3..d26c699ce98 100644 --- a/.changelog/36585.txt +++ b/.changelog/36585.txt @@ -1,3 +1,7 @@ ```release-note:enhancement resource/aws_cloudfront_function: Add `key_value_store_associations` argument ``` + +```release-note:enhancement +data-source/aws_cloudfront_function: Add `key_value_store_associations` attribute +``` \ No newline at end of file From a7ce963997261216e38e54606ef0ea976a02df29 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Mar 2024 08:09:52 -0400 Subject: [PATCH 12/13] Cosmetics. --- internal/service/cloudfront/exports_test.go | 6 +- internal/service/cloudfront/find.go | 26 ------ internal/service/cloudfront/function.go | 89 ++++++++++++------- .../cloudfront/function_data_source.go | 67 ++++++-------- internal/service/cloudfront/function_test.go | 10 +-- .../service/cloudfront/service_package_gen.go | 6 +- 6 files changed, 95 insertions(+), 109 deletions(-) diff --git a/internal/service/cloudfront/exports_test.go b/internal/service/cloudfront/exports_test.go index ea00e494d8c..fa0db979d75 100644 --- a/internal/service/cloudfront/exports_test.go +++ b/internal/service/cloudfront/exports_test.go @@ -6,8 +6,10 @@ package cloudfront // Exports for use in tests only. var ( ResourceContinuousDeploymentPolicy = newResourceContinuousDeploymentPolicy + ResourceFunction = resourceFunction ResourceKeyValueStore = newKeyValueStoreResource - FindKeyValueStoreByName = findKeyValueStoreByName - FindPublicKeyByID = findPublicKeyByID + FindFunctionByTwoPartKey = findFunctionByTwoPartKey + FindKeyValueStoreByName = findKeyValueStoreByName + FindPublicKeyByID = findPublicKeyByID ) diff --git a/internal/service/cloudfront/find.go b/internal/service/cloudfront/find.go index 984389bc31f..a64047b34dc 100644 --- a/internal/service/cloudfront/find.go +++ b/internal/service/cloudfront/find.go @@ -88,32 +88,6 @@ func FindFieldLevelEncryptionProfileByID(ctx context.Context, conn *cloudfront.C return output, nil } -func FindFunctionByNameAndStage(ctx context.Context, conn *cloudfront.CloudFront, name, stage string) (*cloudfront.DescribeFunctionOutput, error) { - input := &cloudfront.DescribeFunctionInput{ - Name: aws.String(name), - Stage: aws.String(stage), - } - - output, err := conn.DescribeFunctionWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, cloudfront.ErrCodeNoSuchFunctionExists) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil || output.FunctionSummary == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output, nil -} - func FindMonitoringSubscriptionByDistributionID(ctx context.Context, conn *cloudfront.CloudFront, id string) (*cloudfront.GetMonitoringSubscriptionOutput, error) { input := &cloudfront.GetMonitoringSubscriptionInput{ DistributionId: aws.String(id), diff --git a/internal/service/cloudfront/function.go b/internal/service/cloudfront/function.go index 7634712fb1c..276bf282951 100644 --- a/internal/service/cloudfront/function.go +++ b/internal/service/cloudfront/function.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/service/cloudfront" "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -19,13 +20,14 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_cloudfront_function") -func ResourceFunction() *schema.Resource { +// @SDKResource("aws_cloudfront_function", name="Function") +func resourceFunction() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceFunctionCreate, ReadWithoutTimeout: resourceFunctionRead, UpdateWithoutTimeout: resourceFunctionUpdate, DeleteWithoutTimeout: resourceFunctionDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -47,6 +49,14 @@ func ResourceFunction() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "key_value_store_associations": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: verify.ValidARN, + }, + }, "live_stage_etag": { Type: schema.TypeString, Computed: true, @@ -70,14 +80,6 @@ func ResourceFunction() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "key_value_store_associations": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: verify.ValidARN, - }, - }, }, } } @@ -100,7 +102,6 @@ func resourceFunctionCreate(ctx context.Context, d *schema.ResourceData, meta in input.FunctionConfig.KeyValueStoreAssociations = expandKeyValueStoreAssociations(v.(*schema.Set).List()) } - log.Printf("[DEBUG] Creating CloudFront Function: %s", functionName) output, err := conn.CreateFunctionWithContext(ctx, input) if err != nil { @@ -115,7 +116,6 @@ func resourceFunctionCreate(ctx context.Context, d *schema.ResourceData, meta in IfMatch: output.ETag, } - log.Printf("[DEBUG] Publishing CloudFront Function: %s", input) _, err := conn.PublishFunctionWithContext(ctx, input) if err != nil { @@ -130,7 +130,7 @@ func resourceFunctionRead(ctx context.Context, d *schema.ResourceData, meta inte var diags diag.Diagnostics conn := meta.(*conns.AWSClient).CloudFrontConn(ctx) - describeFunctionOutput, err := FindFunctionByNameAndStage(ctx, conn, d.Id(), cloudfront.FunctionStageDevelopment) + outputDF, err := findFunctionByTwoPartKey(ctx, conn, d.Id(), cloudfront.FunctionStageDevelopment) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] CloudFront Function (%s) not found, removing from state", d.Id()) @@ -142,14 +142,17 @@ func resourceFunctionRead(ctx context.Context, d *schema.ResourceData, meta inte return sdkdiag.AppendErrorf(diags, "reading CloudFront Function (%s) DEVELOPMENT stage: %s", d.Id(), err) } - d.Set("arn", describeFunctionOutput.FunctionSummary.FunctionMetadata.FunctionARN) - d.Set("comment", describeFunctionOutput.FunctionSummary.FunctionConfig.Comment) - d.Set("etag", describeFunctionOutput.ETag) - d.Set("name", describeFunctionOutput.FunctionSummary.Name) - d.Set("runtime", describeFunctionOutput.FunctionSummary.FunctionConfig.Runtime) - d.Set("status", describeFunctionOutput.FunctionSummary.Status) + d.Set("arn", outputDF.FunctionSummary.FunctionMetadata.FunctionARN) + d.Set("comment", outputDF.FunctionSummary.FunctionConfig.Comment) + d.Set("etag", outputDF.ETag) + if err := d.Set("key_value_store_associations", flattenKeyValueStoreAssociations(outputDF.FunctionSummary.FunctionConfig.KeyValueStoreAssociations)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting key_value_store_associations: %s", err) + } + d.Set("name", outputDF.FunctionSummary.Name) + d.Set("runtime", outputDF.FunctionSummary.FunctionConfig.Runtime) + d.Set("status", outputDF.FunctionSummary.Status) - getFunctionOutput, err := conn.GetFunctionWithContext(ctx, &cloudfront.GetFunctionInput{ + outputGF, err := conn.GetFunctionWithContext(ctx, &cloudfront.GetFunctionInput{ Name: aws.String(d.Id()), Stage: aws.String(cloudfront.FunctionStageDevelopment), }) @@ -158,20 +161,16 @@ func resourceFunctionRead(ctx context.Context, d *schema.ResourceData, meta inte return sdkdiag.AppendErrorf(diags, "reading CloudFront Function (%s) DEVELOPMENT stage code: %s", d.Id(), err) } - d.Set("code", string(getFunctionOutput.FunctionCode)) - - if err := d.Set("key_value_store_associations", flattenKeyValueStoreAssociations(describeFunctionOutput.FunctionSummary.FunctionConfig.KeyValueStoreAssociations)); err != nil { - return sdkdiag.AppendErrorf(diags, "reading CloudFront Function (%s) DEVELOPMENT stage code: %s", d.Id(), err) - } + d.Set("code", string(outputGF.FunctionCode)) - describeFunctionOutput, err = FindFunctionByNameAndStage(ctx, conn, d.Id(), cloudfront.FunctionStageLive) + outputDF, err = findFunctionByTwoPartKey(ctx, conn, d.Id(), cloudfront.FunctionStageLive) if tfresource.NotFound(err) { d.Set("live_stage_etag", "") } else if err != nil { return sdkdiag.AppendErrorf(diags, "reading CloudFront Function (%s) LIVE stage: %s", d.Id(), err) } else { - d.Set("live_stage_etag", describeFunctionOutput.ETag) + d.Set("live_stage_etag", outputDF.ETag) } return diags @@ -182,22 +181,21 @@ func resourceFunctionUpdate(ctx context.Context, d *schema.ResourceData, meta in conn := meta.(*conns.AWSClient).CloudFrontConn(ctx) etag := d.Get("etag").(string) - if d.HasChanges("code", "comment", "runtime", "key_value_store_associations") { + if d.HasChanges("code", "comment", "key_value_store_associations", "runtime") { input := &cloudfront.UpdateFunctionInput{ FunctionCode: []byte(d.Get("code").(string)), FunctionConfig: &cloudfront.FunctionConfig{ Comment: aws.String(d.Get("comment").(string)), Runtime: aws.String(d.Get("runtime").(string)), }, - Name: aws.String(d.Id()), IfMatch: aws.String(etag), + Name: aws.String(d.Id()), } if v, ok := d.GetOk("key_value_store_associations"); ok { input.FunctionConfig.KeyValueStoreAssociations = expandKeyValueStoreAssociations(v.(*schema.Set).List()) } - log.Printf("[INFO] Updating CloudFront Function: %s", d.Id()) output, err := conn.UpdateFunctionWithContext(ctx, input) if err != nil { @@ -209,11 +207,10 @@ func resourceFunctionUpdate(ctx context.Context, d *schema.ResourceData, meta in if d.Get("publish").(bool) { input := &cloudfront.PublishFunctionInput{ - Name: aws.String(d.Id()), IfMatch: aws.String(etag), + Name: aws.String(d.Id()), } - log.Printf("[DEBUG] Publishing CloudFront Function: %s", d.Id()) _, err := conn.PublishFunctionWithContext(ctx, input) if err != nil { @@ -230,8 +227,8 @@ func resourceFunctionDelete(ctx context.Context, d *schema.ResourceData, meta in log.Printf("[INFO] Deleting CloudFront Function: %s", d.Id()) _, err := conn.DeleteFunctionWithContext(ctx, &cloudfront.DeleteFunctionInput{ - Name: aws.String(d.Id()), IfMatch: aws.String(d.Get("etag").(string)), + Name: aws.String(d.Id()), }) if tfawserr.ErrCodeEquals(err, cloudfront.ErrCodeNoSuchFunctionExists) { @@ -245,6 +242,32 @@ func resourceFunctionDelete(ctx context.Context, d *schema.ResourceData, meta in return diags } +func findFunctionByTwoPartKey(ctx context.Context, conn *cloudfront.CloudFront, name, stage string) (*cloudfront.DescribeFunctionOutput, error) { + input := &cloudfront.DescribeFunctionInput{ + Name: aws.String(name), + Stage: aws.String(stage), + } + + output, err := conn.DescribeFunctionWithContext(ctx, input) + + if tfawserr.ErrCodeEquals(err, cloudfront.ErrCodeNoSuchFunctionExists) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.FunctionSummary == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} + func expandKeyValueStoreAssociations(tfList []interface{}) *cloudfront.KeyValueStoreAssociations { if len(tfList) == 0 { return nil diff --git a/internal/service/cloudfront/function_data_source.go b/internal/service/cloudfront/function_data_source.go index 639d2907ca9..e10ff0bd056 100644 --- a/internal/service/cloudfront/function_data_source.go +++ b/internal/service/cloudfront/function_data_source.go @@ -14,11 +14,10 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" - "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKDataSource("aws_cloudfront_function") -func DataSourceFunction() *schema.Resource { +// @SDKDataSource("aws_cloudfront_function", name="Function") +func dataSourceFunction() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceFunctionRead, @@ -27,55 +26,46 @@ func DataSourceFunction() *schema.Resource { Type: schema.TypeString, Computed: true, }, - - "etag": { + "code": { Type: schema.TypeString, Computed: true, }, - - "code": { + "comment": { Type: schema.TypeString, Computed: true, }, - - "comment": { + "etag": { Type: schema.TypeString, Computed: true, }, - + "key_value_store_associations": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "last_modified_time": { Type: schema.TypeString, Computed: true, }, - "name": { Type: schema.TypeString, Required: true, }, - "runtime": { Type: schema.TypeString, Computed: true, }, - "stage": { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice(cloudfront.FunctionStage_Values(), false), }, - "status": { Type: schema.TypeString, Computed: true, }, - "key_value_store_associations": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: verify.ValidARN, - }, - }, }, } } @@ -86,35 +76,34 @@ func dataSourceFunctionRead(ctx context.Context, d *schema.ResourceData, meta in name := d.Get("name").(string) stage := d.Get("stage").(string) - - describeFunctionOutput, err := FindFunctionByNameAndStage(ctx, conn, name, stage) + outputDF, err := findFunctionByTwoPartKey(ctx, conn, name, stage) if err != nil { - return sdkdiag.AppendErrorf(diags, "describing CloudFront Function (%s/%s): %s", name, stage, err) + return sdkdiag.AppendErrorf(diags, "reading CloudFront Function (%s) %s stage: %s", name, stage, err) } - d.Set("arn", describeFunctionOutput.FunctionSummary.FunctionMetadata.FunctionARN) - d.Set("comment", describeFunctionOutput.FunctionSummary.FunctionConfig.Comment) - d.Set("etag", describeFunctionOutput.ETag) - d.Set("last_modified_time", describeFunctionOutput.FunctionSummary.FunctionMetadata.LastModifiedTime.Format(time.RFC3339)) - d.Set("name", describeFunctionOutput.FunctionSummary.Name) - d.Set("runtime", describeFunctionOutput.FunctionSummary.FunctionConfig.Runtime) - d.Set("status", describeFunctionOutput.FunctionSummary.Status) + d.SetId(aws.StringValue(outputDF.FunctionSummary.Name)) + d.Set("arn", outputDF.FunctionSummary.FunctionMetadata.FunctionARN) + d.Set("comment", outputDF.FunctionSummary.FunctionConfig.Comment) + d.Set("etag", outputDF.ETag) + if err := d.Set("key_value_store_associations", flattenKeyValueStoreAssociations(outputDF.FunctionSummary.FunctionConfig.KeyValueStoreAssociations)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting key_value_store_associations: %s", err) + } + d.Set("last_modified_time", outputDF.FunctionSummary.FunctionMetadata.LastModifiedTime.Format(time.RFC3339)) + d.Set("name", outputDF.FunctionSummary.Name) + d.Set("runtime", outputDF.FunctionSummary.FunctionConfig.Runtime) + d.Set("status", outputDF.FunctionSummary.Status) - getFunctionOutput, err := conn.GetFunctionWithContext(ctx, &cloudfront.GetFunctionInput{ + outputGF, err := conn.GetFunctionWithContext(ctx, &cloudfront.GetFunctionInput{ Name: aws.String(name), Stage: aws.String(stage), }) - d.Set("key_value_store_associations", flattenKeyValueStoreAssociations(describeFunctionOutput.FunctionSummary.FunctionConfig.KeyValueStoreAssociations)) - if err != nil { - return sdkdiag.AppendErrorf(diags, "getting CloudFront Function (%s): %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "reading CloudFront Function (%s) %s stage code: %s", name, stage, err) } - d.Set("code", string(getFunctionOutput.FunctionCode)) - - d.SetId(aws.StringValue(describeFunctionOutput.FunctionSummary.Name)) + d.Set("code", string(outputGF.FunctionCode)) return diags } diff --git a/internal/service/cloudfront/function_test.go b/internal/service/cloudfront/function_test.go index 3cbb340451d..2f7c8a06b38 100644 --- a/internal/service/cloudfront/function_test.go +++ b/internal/service/cloudfront/function_test.go @@ -342,7 +342,7 @@ func testAccCheckFunctionDestroy(ctx context.Context) resource.TestCheckFunc { continue } - _, err := tfcloudfront.FindFunctionByNameAndStage(ctx, conn, rs.Primary.ID, cloudfront.FunctionStageDevelopment) + _, err := tfcloudfront.FindFunctionByTwoPartKey(ctx, conn, rs.Primary.ID, cloudfront.FunctionStageDevelopment) if tfresource.NotFound(err) { continue @@ -363,16 +363,12 @@ func testAccCheckFunctionExists(ctx context.Context, n string, v *cloudfront.Des return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("CloudFront Function not found: %s", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("CloudFront Function ID not set") + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).CloudFrontConn(ctx) - output, err := tfcloudfront.FindFunctionByNameAndStage(ctx, conn, rs.Primary.ID, cloudfront.FunctionStageDevelopment) + output, err := tfcloudfront.FindFunctionByTwoPartKey(ctx, conn, rs.Primary.ID, cloudfront.FunctionStageDevelopment) if err != nil { return err diff --git a/internal/service/cloudfront/service_package_gen.go b/internal/service/cloudfront/service_package_gen.go index 958039ef4a8..7a108af2b44 100644 --- a/internal/service/cloudfront/service_package_gen.go +++ b/internal/service/cloudfront/service_package_gen.go @@ -45,8 +45,9 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac TypeName: "aws_cloudfront_distribution", }, { - Factory: DataSourceFunction, + Factory: dataSourceFunction, TypeName: "aws_cloudfront_function", + Name: "Function", }, { Factory: DataSourceLogDeliveryCanonicalUserID, @@ -98,8 +99,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka TypeName: "aws_cloudfront_field_level_encryption_profile", }, { - Factory: ResourceFunction, + Factory: resourceFunction, TypeName: "aws_cloudfront_function", + Name: "Function", }, { Factory: ResourceKeyGroup, From 70082689ac899bbe2dcf88be74f1ca0b1539a815 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Mar 2024 08:11:52 -0400 Subject: [PATCH 13/13] cloudfront: Fixup sweepers. --- internal/service/cloudfront/sweep.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/cloudfront/sweep.go b/internal/service/cloudfront/sweep.go index 113a18ac893..7cb7b2cf3c3 100644 --- a/internal/service/cloudfront/sweep.go +++ b/internal/service/cloudfront/sweep.go @@ -309,7 +309,7 @@ func sweepFunctions(region string) error { for _, item := range page.FunctionList.Items { name := aws.StringValue(item.Name) - output, err := FindFunctionByNameAndStage(ctx, conn, name, cloudfront.FunctionStageDevelopment) + output, err := findFunctionByTwoPartKey(ctx, conn, name, cloudfront.FunctionStageDevelopment) if tfresource.NotFound(err) { continue @@ -322,7 +322,7 @@ func sweepFunctions(region string) error { continue } - r := ResourceFunction() + r := resourceFunction() d := r.Data(nil) d.SetId(name) d.Set("etag", output.ETag)