diff --git a/.changelog/36585.txt b/.changelog/36585.txt new file mode 100644 index 000000000000..d26c699ce989 --- /dev/null +++ b/.changelog/36585.txt @@ -0,0 +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 diff --git a/internal/service/cloudfront/exports_test.go b/internal/service/cloudfront/exports_test.go index ea00e494d8c4..fa0db979d755 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 984389bc31f3..a64047b34dc7 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 c9ec3475dfb4..276bf2829515 100644 --- a/internal/service/cloudfront/function.go +++ b/internal/service/cloudfront/function.go @@ -11,20 +11,23 @@ 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" "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") -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, }, @@ -46,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, @@ -87,7 +98,10 @@ func resourceFunctionCreate(ctx context.Context, d *schema.ResourceData, meta in Name: aws.String(functionName), } - log.Printf("[DEBUG] Creating CloudFront Function: %s", functionName) + if v, ok := d.GetOk("key_value_store_associations"); ok { + input.FunctionConfig.KeyValueStoreAssociations = expandKeyValueStoreAssociations(v.(*schema.Set).List()) + } + output, err := conn.CreateFunctionWithContext(ctx, input) if err != nil { @@ -102,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 { @@ -117,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()) @@ -129,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), }) @@ -145,16 +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)) + 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 @@ -165,18 +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") { + 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 { @@ -188,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 { @@ -209,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) { @@ -223,3 +241,63 @@ 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 + } + + 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 5cfa12a638f1..e10ff0bd056a 100644 --- a/internal/service/cloudfront/function_data_source.go +++ b/internal/service/cloudfront/function_data_source.go @@ -16,8 +16,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" ) -// @SDKDataSource("aws_cloudfront_function") -func DataSourceFunction() *schema.Resource { +// @SDKDataSource("aws_cloudfront_function", name="Function") +func dataSourceFunction() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceFunctionRead, @@ -26,43 +26,42 @@ 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, @@ -77,33 +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), }) 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_data_source_test.go b/internal/service/cloudfront/function_data_source_test.go index cdec47c8cc29..b60feb72d876 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 72f9ebe13e20..2f7c8a06b389 100644 --- a/internal/service/cloudfront/function_test.go +++ b/internal/service/cloudfront/function_test.go @@ -290,6 +290,49 @@ 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"}, + }, + { + 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"), + ), + }, + }, + }) +} + func testAccCheckFunctionDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).CloudFrontConn(ctx) @@ -299,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 @@ -320,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 @@ -577,3 +616,83 @@ 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)) +} + +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)) +} diff --git a/internal/service/cloudfront/service_package_gen.go b/internal/service/cloudfront/service_package_gen.go index 958039ef4a86..7a108af2b444 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, diff --git a/internal/service/cloudfront/sweep.go b/internal/service/cloudfront/sweep.go index 113a18ac893d..7cb7b2cf3c3a 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) diff --git a/website/docs/d/cloudfront_function.html.markdown b/website/docs/d/cloudfront_function.html.markdown index ea91802c5e49..e57940b47f7a 100644 --- a/website/docs/d/cloudfront_function.html.markdown +++ b/website/docs/d/cloudfront_function.html.markdown @@ -37,6 +37,7 @@ 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`. diff --git a/website/docs/r/cloudfront_function.html.markdown b/website/docs/r/cloudfront_function.html.markdown index df52b5627c61..f51aa9c0383e 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. AWS limits associations to on key value store per function. ## Attribute Reference