From 5d92ba4f023d2510960e94e8a801eaaab1caf027 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Tue, 29 Nov 2022 00:15:20 +0200 Subject: [PATCH 1/9] appsync function code --- internal/service/appsync/appsync_test.go | 1 + internal/service/appsync/function.go | 152 ++++++++++++++---- internal/service/appsync/function_test.go | 90 ++++++++--- internal/service/appsync/resolver.go | 104 ++++++++---- .../test-fixtures/test-code-updated.js | 20 +++ .../appsync/test-fixtures/test-code.js | 20 +++ 6 files changed, 305 insertions(+), 82 deletions(-) create mode 100644 internal/service/appsync/test-fixtures/test-code-updated.js create mode 100644 internal/service/appsync/test-fixtures/test-code.js diff --git a/internal/service/appsync/appsync_test.go b/internal/service/appsync/appsync_test.go index 26faa7f6e65..4bc16aabb41 100644 --- a/internal/service/appsync/appsync_test.go +++ b/internal/service/appsync/appsync_test.go @@ -61,6 +61,7 @@ func TestAccAppSync_serial(t *testing.T) { }, "Function": { "basic": testAccFunction_basic, + "code": testAccFunction_code, "disappears": testAccFunction_disappears, "description": testAccFunction_description, "responseMappingTemplate": testAccFunction_responseMappingTemplate, diff --git a/internal/service/appsync/function.go b/internal/service/appsync/function.go index c30fc76bbf2..258419e064a 100644 --- a/internal/service/appsync/function.go +++ b/internal/service/appsync/function.go @@ -32,10 +32,35 @@ func ResourceFunction() *schema.Resource { Required: true, ForceNew: true, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "code": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 32768), + }, "data_source": { Type: schema.TypeString, Required: true, }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "function_id": { + Type: schema.TypeString, + Computed: true, + }, + "function_version": { + Type: schema.TypeString, + Optional: true, + Default: "2018-05-29", + ValidateFunc: validation.StringInSlice([]string{ + "2018-05-29", + }, true), + }, "max_batch_size": { Type: schema.TypeInt, Optional: true, @@ -48,27 +73,29 @@ func ResourceFunction() *schema.Resource { }, "request_mapping_template": { Type: schema.TypeString, - Required: true, + Optional: true, }, "response_mapping_template": { - Type: schema.TypeString, - Required: true, - }, - "description": { Type: schema.TypeString, Optional: true, }, - "function_version": { - Type: schema.TypeString, + "runtime": { + Type: schema.TypeList, Optional: true, - Default: "2018-05-29", - ValidateFunc: validation.StringInSlice([]string{ - "2018-05-29", - }, true), - }, - "arn": { - Type: schema.TypeString, - Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(appsync.RuntimeName_Values(), false), + }, + "runtime_version": { + Type: schema.TypeString, + Required: true, + }, + }, + }, }, "sync_config": { Type: schema.TypeList, @@ -103,10 +130,6 @@ func ResourceFunction() *schema.Resource { }, }, }, - "function_id": { - Type: schema.TypeString, - Computed: true, - }, }, } } @@ -117,17 +140,25 @@ func resourceFunctionCreate(d *schema.ResourceData, meta interface{}) error { apiID := d.Get("api_id").(string) input := &appsync.CreateFunctionInput{ - ApiId: aws.String(apiID), - DataSourceName: aws.String(d.Get("data_source").(string)), - FunctionVersion: aws.String(d.Get("function_version").(string)), - Name: aws.String(d.Get("name").(string)), - RequestMappingTemplate: aws.String(d.Get("request_mapping_template").(string)), + ApiId: aws.String(apiID), + DataSourceName: aws.String(d.Get("data_source").(string)), + FunctionVersion: aws.String(d.Get("function_version").(string)), + Name: aws.String(d.Get("name").(string)), + } + + if v, ok := d.GetOk("code"); ok { + input.Code = aws.String(v.(string)) + input.FunctionVersion = nil } if v, ok := d.GetOk("description"); ok { input.Description = aws.String(v.(string)) } + if v, ok := d.GetOk("request_mapping_template"); ok { + input.RequestMappingTemplate = aws.String(v.(string)) + } + if v, ok := d.GetOk("response_mapping_template"); ok { input.ResponseMappingTemplate = aws.String(v.(string)) } @@ -140,9 +171,13 @@ func resourceFunctionCreate(d *schema.ResourceData, meta interface{}) error { input.SyncConfig = expandSyncConfig(v.([]interface{})) } + if v, ok := d.GetOk("runtime"); ok && len(v.([]interface{})) > 0 { + input.Runtime = expandRuntime(v.([]interface{})) + } + resp, err := conn.CreateFunction(input) if err != nil { - return fmt.Errorf("Error creating AppSync Function: %w", err) + return fmt.Errorf("error creating AppSync Function: %w", err) } d.SetId(fmt.Sprintf("%s-%s", apiID, aws.StringValue(resp.FunctionConfiguration.FunctionId))) @@ -170,7 +205,7 @@ func resourceFunctionRead(d *schema.ResourceData, meta interface{}) error { return nil } if err != nil { - return fmt.Errorf("Error getting AppSync Function %s: %w", d.Id(), err) + return fmt.Errorf("error getting AppSync Function %s: %w", d.Id(), err) } function := resp.FunctionConfiguration @@ -184,11 +219,16 @@ func resourceFunctionRead(d *schema.ResourceData, meta interface{}) error { d.Set("request_mapping_template", function.RequestMappingTemplate) d.Set("response_mapping_template", function.ResponseMappingTemplate) d.Set("max_batch_size", function.MaxBatchSize) + d.Set("code", function.Code) if err := d.Set("sync_config", flattenSyncConfig(function.SyncConfig)); err != nil { return fmt.Errorf("error setting sync_config: %w", err) } + if err := d.Set("runtime", flattenRuntime(function.Runtime)); err != nil { + return fmt.Errorf("error setting runtime: %w", err) + } + return nil } @@ -201,18 +241,25 @@ func resourceFunctionUpdate(d *schema.ResourceData, meta interface{}) error { } input := &appsync.UpdateFunctionInput{ - ApiId: aws.String(apiID), - DataSourceName: aws.String(d.Get("data_source").(string)), - FunctionId: aws.String(functionID), - FunctionVersion: aws.String(d.Get("function_version").(string)), - Name: aws.String(d.Get("name").(string)), - RequestMappingTemplate: aws.String(d.Get("request_mapping_template").(string)), + ApiId: aws.String(apiID), + DataSourceName: aws.String(d.Get("data_source").(string)), + FunctionId: aws.String(functionID), + FunctionVersion: aws.String(d.Get("function_version").(string)), + Name: aws.String(d.Get("name").(string)), } if v, ok := d.GetOk("description"); ok { input.Description = aws.String(v.(string)) } + if v, ok := d.GetOk("code"); ok { + input.Code = aws.String(v.(string)) + } + + if v, ok := d.GetOk("request_mapping_template"); ok { + input.RequestMappingTemplate = aws.String(v.(string)) + } + if v, ok := d.GetOk("response_mapping_template"); ok { input.ResponseMappingTemplate = aws.String(v.(string)) } @@ -225,9 +272,13 @@ func resourceFunctionUpdate(d *schema.ResourceData, meta interface{}) error { input.SyncConfig = expandSyncConfig(v.([]interface{})) } + if v, ok := d.GetOk("runtime"); ok && len(v.([]interface{})) > 0 { + input.Runtime = expandRuntime(v.([]interface{})) + } + _, err = conn.UpdateFunction(input) if err != nil { - return fmt.Errorf("Error updating AppSync Function %s: %w", d.Id(), err) + return fmt.Errorf("error updating AppSync Function %s: %w", d.Id(), err) } return resourceFunctionRead(d, meta) @@ -251,7 +302,7 @@ func resourceFunctionDelete(d *schema.ResourceData, meta interface{}) error { return nil } if err != nil { - return fmt.Errorf("Error deleting AppSync Function %s: %w", d.Id(), err) + return fmt.Errorf("error deleting AppSync Function %s: %w", d.Id(), err) } return nil @@ -265,6 +316,39 @@ func DecodeFunctionID(id string) (string, string, error) { return idParts[0], idParts[1], nil } +func expandRuntime(l []interface{}) *appsync.AppSyncRuntime { + if len(l) == 0 || l[0] == nil { + return nil + } + + configured := l[0].(map[string]interface{}) + + result := &appsync.AppSyncRuntime{} + + if v, ok := configured["name"].(string); ok { + result.Name = aws.String(v) + } + + if v, ok := configured["runtime_version"].(string); ok { + result.RuntimeVersion = aws.String(v) + } + + return result +} + +func flattenRuntime(config *appsync.AppSyncRuntime) []map[string]interface{} { + if config == nil { + return nil + } + + result := map[string]interface{}{ + "name": aws.StringValue(config.Name), + "runtime_version": aws.StringValue(config.RuntimeVersion), + } + + return []map[string]interface{}{result} +} + func expandSyncConfig(l []interface{}) *appsync.SyncConfig { if len(l) == 0 || l[0] == nil { return nil diff --git a/internal/service/appsync/function_test.go b/internal/service/appsync/function_test.go index 61308578582..74d7ccf2300 100644 --- a/internal/service/appsync/function_test.go +++ b/internal/service/appsync/function_test.go @@ -37,6 +37,7 @@ func testAccFunction_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "name", rName2), resource.TestCheckResourceAttr(resourceName, "description", ""), resource.TestCheckResourceAttr(resourceName, "max_batch_size", "0"), + resource.TestCheckResourceAttr(resourceName, "runtime.#", "0"), resource.TestCheckResourceAttr(resourceName, "sync_config.#", "0"), resource.TestCheckResourceAttrPair(resourceName, "api_id", "aws_appsync_graphql_api.test", "id"), resource.TestCheckResourceAttrPair(resourceName, "data_source", "aws_appsync_datasource.test", "name"), @@ -58,6 +59,49 @@ func testAccFunction_basic(t *testing.T) { }) } +func testAccFunction_code(t *testing.T) { + rName1 := fmt.Sprintf("tfacctest%d", sdkacctest.RandInt()) + rName2 := fmt.Sprintf("tfexample%s", sdkacctest.RandString(8)) + resourceName := "aws_appsync_function.test" + var config appsync.FunctionConfiguration + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckPartitionHasService(appsync.EndpointsID, t) }, + ErrorCheck: acctest.ErrorCheck(t, appsync.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckFunctionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccFunctionConfig_code(rName1, rName2, "test-fixtures/test-code.js"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFunctionExists(resourceName, &config), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + resource.TestCheckResourceAttrSet(resourceName, "code"), + resource.TestCheckResourceAttr(resourceName, "runtime.#", "1"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.name", "APPSYNC_JS"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.runtime_version", "1.0.0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccFunctionConfig_code(rName1, rName2, "test-fixtures/test-code-updated.js"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFunctionExists(resourceName, &config), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + resource.TestCheckResourceAttrSet(resourceName, "code"), + resource.TestCheckResourceAttr(resourceName, "runtime.#", "1"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.name", "APPSYNC_JS"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.runtime_version", "1.0.0"), + ), + }, + }, + }) +} + func testAccFunction_syncConfig(t *testing.T) { rName := fmt.Sprintf("tfacctest%d", sdkacctest.RandInt()) resourceName := "aws_appsync_function.test" @@ -233,13 +277,11 @@ func testAccCheckFunctionExists(name string, config *appsync.FunctionConfigurati } func testAccFunctionConfig_basic(r1, r2, region string) string { - return fmt.Sprintf(` -%[1]s - + return acctest.ConfigCompose(testAccDataSourceConfig_dynamoDBRegion(r1, region), fmt.Sprintf(` resource "aws_appsync_function" "test" { api_id = aws_appsync_graphql_api.test.id data_source = aws_appsync_datasource.test.name - name = "%[2]s" + name = %[1]q request_mapping_template = < 0 { + input.Runtime = expandRuntime(v.([]interface{})) + } + mutexKey := fmt.Sprintf("appsync-schema-%s", d.Get("api_id").(string)) conns.GlobalMutexKV.Lock(mutexKey) defer conns.GlobalMutexKV.Unlock(mutexKey) @@ -241,11 +272,16 @@ func resourceResolverRead(d *schema.ResourceData, meta interface{}) error { d.Set("response_template", resolver.ResponseMappingTemplate) d.Set("kind", resolver.Kind) d.Set("max_batch_size", resolver.MaxBatchSize) + d.Set("code", resolver.Code) if err := d.Set("sync_config", flattenSyncConfig(resolver.SyncConfig)); err != nil { return fmt.Errorf("error setting sync_config: %w", err) } + if err := d.Set("runtime", flattenRuntime(resolver.Runtime)); err != nil { + return fmt.Errorf("error setting runtime: %w", err) + } + if err := d.Set("pipeline_config", flattenPipelineConfig(resolver.PipelineConfig)); err != nil { return fmt.Errorf("Error setting pipeline_config: %w", err) } @@ -271,6 +307,14 @@ func resourceResolverUpdate(d *schema.ResourceData, meta interface{}) error { input.DataSourceName = aws.String(v.(string)) } + if v, ok := d.GetOk("code"); ok { + input.Code = aws.String(v.(string)) + } + + if v, ok := d.GetOk("runtime"); ok && len(v.([]interface{})) > 0 { + input.Runtime = expandRuntime(v.([]interface{})) + } + if v, ok := d.GetOk("pipeline_config"); ok { config := v.([]interface{})[0].(map[string]interface{}) input.PipelineConfig = &appsync.PipelineConfig{ diff --git a/internal/service/appsync/test-fixtures/test-code-updated.js b/internal/service/appsync/test-fixtures/test-code-updated.js new file mode 100644 index 00000000000..cccf930150f --- /dev/null +++ b/internal/service/appsync/test-fixtures/test-code-updated.js @@ -0,0 +1,20 @@ +import { util } from '@aws-appsync/utils'; + +/** + * Request a single item from the attached DynamoDB table update + * @param ctx the request context + */ +export function request(ctx) { + return { + operation: 'GetItem', + key: util.dynamodb.toMapValues({ id: ctx.args.id }), + }; +} + +/** + * Returns the DynamoDB result directly + * @param ctx the request context + */ +export function response(ctx) { + return ctx.result; +} \ No newline at end of file diff --git a/internal/service/appsync/test-fixtures/test-code.js b/internal/service/appsync/test-fixtures/test-code.js new file mode 100644 index 00000000000..b9da7287553 --- /dev/null +++ b/internal/service/appsync/test-fixtures/test-code.js @@ -0,0 +1,20 @@ +import { util } from '@aws-appsync/utils'; + +/** + * Request a single item from the attached DynamoDB table + * @param ctx the request context + */ +export function request(ctx) { + return { + operation: 'GetItem', + key: util.dynamodb.toMapValues({ id: ctx.args.id }), + }; +} + +/** + * Returns the DynamoDB result directly + * @param ctx the request context + */ +export function response(ctx) { + return ctx.result; +} \ No newline at end of file From ca62195c29f0f283a36dd5e318175c5642a2945c Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Tue, 29 Nov 2022 00:26:30 +0200 Subject: [PATCH 2/9] edge case --- internal/service/appsync/function.go | 12 +++++++----- website/docs/r/appsync_function.html.markdown | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/internal/service/appsync/function.go b/internal/service/appsync/function.go index 258419e064a..baf6abc8011 100644 --- a/internal/service/appsync/function.go +++ b/internal/service/appsync/function.go @@ -39,6 +39,7 @@ func ResourceFunction() *schema.Resource { "code": { Type: schema.TypeString, Optional: true, + RequiredWith: []string{"runtime"}, ValidateFunc: validation.StringLenBetween(1, 32768), }, "data_source": { @@ -56,7 +57,7 @@ func ResourceFunction() *schema.Resource { "function_version": { Type: schema.TypeString, Optional: true, - Default: "2018-05-29", + Computed: true, ValidateFunc: validation.StringInSlice([]string{ "2018-05-29", }, true), @@ -80,9 +81,10 @@ func ResourceFunction() *schema.Resource { Optional: true, }, "runtime": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + RequiredWith: []string{"code"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -148,7 +150,6 @@ func resourceFunctionCreate(d *schema.ResourceData, meta interface{}) error { if v, ok := d.GetOk("code"); ok { input.Code = aws.String(v.(string)) - input.FunctionVersion = nil } if v, ok := d.GetOk("description"); ok { @@ -157,6 +158,7 @@ func resourceFunctionCreate(d *schema.ResourceData, meta interface{}) error { if v, ok := d.GetOk("request_mapping_template"); ok { input.RequestMappingTemplate = aws.String(v.(string)) + input.FunctionVersion = aws.String("2018-05-29") } if v, ok := d.GetOk("response_mapping_template"); ok { diff --git a/website/docs/r/appsync_function.html.markdown b/website/docs/r/appsync_function.html.markdown index 7eccbafe3f1..421764f5fd8 100644 --- a/website/docs/r/appsync_function.html.markdown +++ b/website/docs/r/appsync_function.html.markdown @@ -77,14 +77,23 @@ EOF The following arguments are supported: * `api_id` - (Required) ID of the associated AppSync API. +* `code` - (Optional) The function code that contains the request and response functions. When code is used, the runtime is required. The runtime value must be APPSYNC_JS. * `data_source` - (Required) Function data source name. * `max_batch_size` - (Optional) Maximum batching size for a resolver. Valid values are between `0` and `2000`. * `name` - (Required) Function name. The function name does not have to be unique. -* `request_mapping_template` - (Required) Function request mapping template. Functions support only the 2018-05-29 version of the request mapping template. -* `response_mapping_template` - (Required) Function response mapping template. +* `request_mapping_template` - (Optional) Function request mapping template. Functions support only the 2018-05-29 version of the request mapping template. +* `response_mapping_template` - (Optional) Function response mapping template. * `description` - (Optional) Function description. +* `runtime` - (Optional) Describes a runtime used by an AWS AppSync pipeline resolver or AWS AppSync function. Specifies the name and version of the runtime to use. Note that if a runtime is specified, code must also be specified. See [Runtime](#runtime). * `sync_config` - (Optional) Describes a Sync configuration for a resolver. See [Sync Config](#sync-config). -* `function_version` - (Optional) Version of the request mapping template. Currently the supported value is `2018-05-29`. +* `function_version` - (Optional) Version of the request mapping template. Currently the supported value is `2018-05-29`. Does not apply when specifying `code`. + +### Runtime + +The following arguments are supported: + +* `name` - (Optional) The name of the runtime to use. Currently, the only allowed value is `APPSYNC_JS`. +* `runtime_version` - (Optional) The version of the runtime to use. Currently, the only allowed version is `1.0.0`. ### Sync Config From 204a7347a6374b103da9f499f626d507e64947c3 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Tue, 29 Nov 2022 00:30:40 +0200 Subject: [PATCH 3/9] changelog --- .changelog/28057.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changelog/28057.txt diff --git a/.changelog/28057.txt b/.changelog/28057.txt new file mode 100644 index 00000000000..a5551a0cf3d --- /dev/null +++ b/.changelog/28057.txt @@ -0,0 +1,11 @@ +```release-note:enhancement +resource/aws_appsync_function: Add `runtime` and `code` arguments +``` + +```release-note:enhancement +resource/aws_appsync_function: Make `request_mapping_template` and `response_mapping_template` Optional +``` + +```release-note:enhancement +resource/aws_appsync_resolver: Add `runtime` and `code` arguments +``` \ No newline at end of file From 9c38d4a14e87a207f9ac1723f577c3026f8ca1f4 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Tue, 29 Nov 2022 00:36:03 +0200 Subject: [PATCH 4/9] resolver --- internal/service/appsync/resolver.go | 8 ++- internal/service/appsync/resolver_test.go | 59 +++++++++++++++++++ website/docs/r/appsync_resolver.html.markdown | 9 +++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/internal/service/appsync/resolver.go b/internal/service/appsync/resolver.go index 8b30a1f434f..2c199259029 100644 --- a/internal/service/appsync/resolver.go +++ b/internal/service/appsync/resolver.go @@ -61,6 +61,7 @@ func ResourceResolver() *schema.Resource { "code": { Type: schema.TypeString, Optional: true, + RequiredWith: []string{"runtime"}, ValidateFunc: validation.StringLenBetween(1, 32768), }, "data_source": { @@ -110,9 +111,10 @@ func ResourceResolver() *schema.Resource { Optional: true, }, "runtime": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + RequiredWith: []string{"code"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { diff --git a/internal/service/appsync/resolver_test.go b/internal/service/appsync/resolver_test.go index 41523a67d4e..61b50e525f7 100644 --- a/internal/service/appsync/resolver_test.go +++ b/internal/service/appsync/resolver_test.go @@ -36,6 +36,7 @@ func testAccResolver_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "request_template"), resource.TestCheckResourceAttr(resourceName, "max_batch_size", "0"), resource.TestCheckResourceAttr(resourceName, "sync_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "runtime.#", "0"), ), }, { @@ -47,6 +48,46 @@ func testAccResolver_basic(t *testing.T) { }) } +func testAccResolver_code(t *testing.T) { + var resolver1 appsync.Resolver + rName := fmt.Sprintf("tfacctest%d", sdkacctest.RandInt()) + resourceName := "aws_appsync_resolver.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckPartitionHasService(appsync.EndpointsID, t) }, + ErrorCheck: acctest.ErrorCheck(t, appsync.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckResolverDestroy, + Steps: []resource.TestStep{ + { + Config: testAccResolverConfig_code(rName, "test-fixtures/test-code.js"), + Check: resource.ComposeTestCheckFunc( + testAccCheckResolverExists(resourceName, &resolver1), + resource.TestCheckResourceAttrSet(resourceName, "code"), + resource.TestCheckResourceAttr(resourceName, "runtime.#", "1"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.name", "APPSYNC_JS"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.runtime_version", "1.0.0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccResolverConfig_code(rName, "test-fixtures/test-code-updated.js"), + Check: resource.ComposeTestCheckFunc( + testAccCheckResolverExists(resourceName, &resolver1), + resource.TestCheckResourceAttrSet(resourceName, "code"), + resource.TestCheckResourceAttr(resourceName, "runtime.#", "1"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.name", "APPSYNC_JS"), + resource.TestCheckResourceAttr(resourceName, "runtime.0.runtime_version", "1.0.0"), + ), + }, + }, + }) +} + func testAccResolver_syncConfig(t *testing.T) { var resolver1 appsync.Resolver rName := fmt.Sprintf("tfacctest%d", sdkacctest.RandInt()) @@ -454,6 +495,24 @@ EOF ` } +func testAccResolverConfig_code(rName, code string) string { + return testAccResolverConfig_base(rName) + ` +resource "aws_appsync_resolver" "test" { + api_id = aws_appsync_graphql_api.test.id + field = "singlePost" + type = "Query" + data_source = aws_appsync_datasource.test.name + + code = file("%[2]s") + + runtime { + name = "APPSYNC_JS" + runtime_version = "1.0.0" + } +} +` +} + func testAccResolverConfig_dataSource(rName string) string { return testAccResolverConfig_base(rName) + ` resource "aws_appsync_datasource" "test2" { diff --git a/website/docs/r/appsync_resolver.html.markdown b/website/docs/r/appsync_resolver.html.markdown index 49d034122a4..b6cbc38385b 100644 --- a/website/docs/r/appsync_resolver.html.markdown +++ b/website/docs/r/appsync_resolver.html.markdown @@ -106,6 +106,7 @@ resource "aws_appsync_resolver" "Mutation_pipelineTest" { The following arguments are supported: * `api_id` - (Required) API ID for the GraphQL API. +* `code` - (Optional) The function code that contains the request and response functions. When code is used, the runtime is required. The runtime value must be APPSYNC_JS. * `type` - (Required) Type name from the schema defined in the GraphQL API. * `field` - (Required) Field name from the schema defined in the GraphQL API. * `request_template` - (Optional) Request mapping template for UNIT resolver or 'before mapping template' for PIPELINE resolver. Required for non-Lambda resolvers. @@ -114,12 +115,20 @@ The following arguments are supported: * `max_batch_size` - (Optional) Maximum batching size for a resolver. Valid values are between `0` and `2000`. * `kind` - (Optional) Resolver type. Valid values are `UNIT` and `PIPELINE`. * `sync_config` - (Optional) Describes a Sync configuration for a resolver. See [Sync Config](#sync-config). +* `runtime` - (Optional) Describes a runtime used by an AWS AppSync pipeline resolver or AWS AppSync function. Specifies the name and version of the runtime to use. Note that if a runtime is specified, code must also be specified. See [Runtime](#runtime). * `pipeline_config` - (Optional) PipelineConfig. * `functions` - (Required) List of Function ID. * `caching_config` - (Optional) CachingConfig. * `caching_keys` - (Optional) List of caching key. * `ttl` - (Optional) TTL in seconds. +### Runtime + +The following arguments are supported: + +* `name` - (Optional) The name of the runtime to use. Currently, the only allowed value is `APPSYNC_JS`. +* `runtime_version` - (Optional) The version of the runtime to use. Currently, the only allowed version is `1.0.0`. + ### Sync Config The following arguments are supported: From c58dd0fa82360f64f6c0fe13b2e0eb68608355c9 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Tue, 29 Nov 2022 11:16:47 +0200 Subject: [PATCH 5/9] docs + missing test --- internal/service/appsync/appsync_test.go | 1 + website/docs/r/appsync_function.html.markdown | 16 +++++++ website/docs/r/appsync_resolver.html.markdown | 42 +++++++++++++------ 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/internal/service/appsync/appsync_test.go b/internal/service/appsync/appsync_test.go index 4bc16aabb41..7b0364f15dd 100644 --- a/internal/service/appsync/appsync_test.go +++ b/internal/service/appsync/appsync_test.go @@ -69,6 +69,7 @@ func TestAccAppSync_serial(t *testing.T) { }, "Resolver": { "basic": testAccResolver_basic, + "code": testAccResolver_code, "disappears": testAccResolver_disappears, "dataSource": testAccResolver_dataSource, "DataSource_lambda": testAccResolver_DataSource_lambda, diff --git a/website/docs/r/appsync_function.html.markdown b/website/docs/r/appsync_function.html.markdown index 421764f5fd8..aef5b9722ca 100644 --- a/website/docs/r/appsync_function.html.markdown +++ b/website/docs/r/appsync_function.html.markdown @@ -72,6 +72,22 @@ EOF } ``` +## Example Usage With Code + +```terraform +resource "aws_appsync_function" "example" { + api_id = aws_appsync_graphql_api.example.id + data_source = aws_appsync_datasource.example.name + name = "example" + code = file("some-code-dir") + + runtime { + name = "APPSYNC_JS" + runtime_version = "1.0.0" + } +} +``` + ## Argument Reference The following arguments are supported: diff --git a/website/docs/r/appsync_resolver.html.markdown b/website/docs/r/appsync_resolver.html.markdown index b6cbc38385b..19ec2c46459 100644 --- a/website/docs/r/appsync_resolver.html.markdown +++ b/website/docs/r/appsync_resolver.html.markdown @@ -13,7 +13,7 @@ Provides an AppSync Resolver. ## Example Usage ```terraform -resource "aws_appsync_graphql_api" "test" { +resource "aws_appsync_graphql_api" "example" { authentication_type = "API_KEY" name = "tf-example" @@ -38,8 +38,8 @@ schema { EOF } -resource "aws_appsync_datasource" "test" { - api_id = aws_appsync_graphql_api.test.id +resource "aws_appsync_datasource" "example" { + api_id = aws_appsync_graphql_api.example.id name = "tf_example" type = "HTTP" @@ -49,11 +49,11 @@ resource "aws_appsync_datasource" "test" { } # UNIT type resolver (default) -resource "aws_appsync_resolver" "test" { - api_id = aws_appsync_graphql_api.test.id +resource "aws_appsync_resolver" "example" { + api_id = aws_appsync_graphql_api.example.id field = "singlePost" type = "Query" - data_source = aws_appsync_datasource.test.name + data_source = aws_appsync_datasource.example.name request_template = < Date: Tue, 29 Nov 2022 11:22:16 +0200 Subject: [PATCH 6/9] code test fix resolver --- internal/service/appsync/resolver_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/service/appsync/resolver_test.go b/internal/service/appsync/resolver_test.go index 61b50e525f7..cd7acd3560a 100644 --- a/internal/service/appsync/resolver_test.go +++ b/internal/service/appsync/resolver_test.go @@ -496,21 +496,21 @@ EOF } func testAccResolverConfig_code(rName, code string) string { - return testAccResolverConfig_base(rName) + ` + return acctest.ConfigCompose(testAccResolverConfig_base(rName), fmt.Sprintf(` resource "aws_appsync_resolver" "test" { api_id = aws_appsync_graphql_api.test.id field = "singlePost" type = "Query" data_source = aws_appsync_datasource.test.name - code = file("%[2]s") + code = file("%[1]s") runtime { name = "APPSYNC_JS" runtime_version = "1.0.0" } } -` +`, code)) } func testAccResolverConfig_dataSource(rName string) string { From dcfe4f914c750fa4aad09d225e13365c9e5464da Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Fri, 2 Dec 2022 18:09:03 +0200 Subject: [PATCH 7/9] changelog --- internal/service/appsync/resolver.go | 110 +++++------------- internal/service/appsync/resolver_test.go | 59 ---------- website/docs/r/appsync_resolver.html.markdown | 51 ++------ 3 files changed, 44 insertions(+), 176 deletions(-) diff --git a/internal/service/appsync/resolver.go b/internal/service/appsync/resolver.go index 2c199259029..0fe49f92506 100644 --- a/internal/service/appsync/resolver.go +++ b/internal/service/appsync/resolver.go @@ -34,45 +34,33 @@ func ResourceResolver() *schema.Resource { Required: true, ForceNew: true, }, - "arn": { + "type": { Type: schema.TypeString, - Computed: true, - }, - "caching_config": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "caching_keys": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "ttl": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, + Required: true, + ForceNew: true, }, - "code": { - Type: schema.TypeString, - Optional: true, - RequiredWith: []string{"runtime"}, - ValidateFunc: validation.StringLenBetween(1, 32768), + "field": { + Type: schema.TypeString, + Required: true, + ForceNew: true, }, "data_source": { Type: schema.TypeString, Optional: true, ConflictsWith: []string{"pipeline_config"}, }, - "field": { + "max_batch_size": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 2000), + }, + "request_template": { Type: schema.TypeString, - Required: true, - ForceNew: true, + Optional: true, + }, + "response_template": { + Type: schema.TypeString, + Optional: true, }, "kind": { Type: schema.TypeString, @@ -80,11 +68,6 @@ func ResourceResolver() *schema.Resource { Default: appsync.ResolverKindUnit, ValidateFunc: validation.StringInSlice(appsync.ResolverKind_Values(), true), }, - "max_batch_size": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(0, 2000), - }, "pipeline_config": { Type: schema.TypeList, Optional: true, @@ -102,29 +85,22 @@ func ResourceResolver() *schema.Resource { }, }, }, - "request_template": { - Type: schema.TypeString, - Optional: true, - }, - "response_template": { - Type: schema.TypeString, + "caching_config": { + Type: schema.TypeList, Optional: true, - }, - "runtime": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - RequiredWith: []string{"code"}, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(appsync.RuntimeName_Values(), false), + "caching_keys": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - "runtime_version": { - Type: schema.TypeString, - Required: true, + "ttl": { + Type: schema.TypeInt, + Optional: true, }, }, }, @@ -162,10 +138,9 @@ func ResourceResolver() *schema.Resource { }, }, }, - "type": { + "arn": { Type: schema.TypeString, - Required: true, - ForceNew: true, + Computed: true, }, }, } @@ -181,10 +156,6 @@ func resourceResolverCreate(d *schema.ResourceData, meta interface{}) error { Kind: aws.String(d.Get("kind").(string)), } - if v, ok := d.GetOk("code"); ok { - input.Code = aws.String(v.(string)) - } - if v, ok := d.GetOkExists("max_batch_size"); ok { input.MaxBatchSize = aws.Int64(int64(v.(int))) } @@ -216,10 +187,6 @@ func resourceResolverCreate(d *schema.ResourceData, meta interface{}) error { input.CachingConfig = expandResolverCachingConfig(v.([]interface{})) } - if v, ok := d.GetOk("runtime"); ok && len(v.([]interface{})) > 0 { - input.Runtime = expandRuntime(v.([]interface{})) - } - mutexKey := fmt.Sprintf("appsync-schema-%s", d.Get("api_id").(string)) conns.GlobalMutexKV.Lock(mutexKey) defer conns.GlobalMutexKV.Unlock(mutexKey) @@ -274,16 +241,11 @@ func resourceResolverRead(d *schema.ResourceData, meta interface{}) error { d.Set("response_template", resolver.ResponseMappingTemplate) d.Set("kind", resolver.Kind) d.Set("max_batch_size", resolver.MaxBatchSize) - d.Set("code", resolver.Code) if err := d.Set("sync_config", flattenSyncConfig(resolver.SyncConfig)); err != nil { return fmt.Errorf("error setting sync_config: %w", err) } - if err := d.Set("runtime", flattenRuntime(resolver.Runtime)); err != nil { - return fmt.Errorf("error setting runtime: %w", err) - } - if err := d.Set("pipeline_config", flattenPipelineConfig(resolver.PipelineConfig)); err != nil { return fmt.Errorf("Error setting pipeline_config: %w", err) } @@ -309,14 +271,6 @@ func resourceResolverUpdate(d *schema.ResourceData, meta interface{}) error { input.DataSourceName = aws.String(v.(string)) } - if v, ok := d.GetOk("code"); ok { - input.Code = aws.String(v.(string)) - } - - if v, ok := d.GetOk("runtime"); ok && len(v.([]interface{})) > 0 { - input.Runtime = expandRuntime(v.([]interface{})) - } - if v, ok := d.GetOk("pipeline_config"); ok { config := v.([]interface{})[0].(map[string]interface{}) input.PipelineConfig = &appsync.PipelineConfig{ diff --git a/internal/service/appsync/resolver_test.go b/internal/service/appsync/resolver_test.go index cd7acd3560a..41523a67d4e 100644 --- a/internal/service/appsync/resolver_test.go +++ b/internal/service/appsync/resolver_test.go @@ -36,7 +36,6 @@ func testAccResolver_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "request_template"), resource.TestCheckResourceAttr(resourceName, "max_batch_size", "0"), resource.TestCheckResourceAttr(resourceName, "sync_config.#", "0"), - resource.TestCheckResourceAttr(resourceName, "runtime.#", "0"), ), }, { @@ -48,46 +47,6 @@ func testAccResolver_basic(t *testing.T) { }) } -func testAccResolver_code(t *testing.T) { - var resolver1 appsync.Resolver - rName := fmt.Sprintf("tfacctest%d", sdkacctest.RandInt()) - resourceName := "aws_appsync_resolver.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckPartitionHasService(appsync.EndpointsID, t) }, - ErrorCheck: acctest.ErrorCheck(t, appsync.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckResolverDestroy, - Steps: []resource.TestStep{ - { - Config: testAccResolverConfig_code(rName, "test-fixtures/test-code.js"), - Check: resource.ComposeTestCheckFunc( - testAccCheckResolverExists(resourceName, &resolver1), - resource.TestCheckResourceAttrSet(resourceName, "code"), - resource.TestCheckResourceAttr(resourceName, "runtime.#", "1"), - resource.TestCheckResourceAttr(resourceName, "runtime.0.name", "APPSYNC_JS"), - resource.TestCheckResourceAttr(resourceName, "runtime.0.runtime_version", "1.0.0"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccResolverConfig_code(rName, "test-fixtures/test-code-updated.js"), - Check: resource.ComposeTestCheckFunc( - testAccCheckResolverExists(resourceName, &resolver1), - resource.TestCheckResourceAttrSet(resourceName, "code"), - resource.TestCheckResourceAttr(resourceName, "runtime.#", "1"), - resource.TestCheckResourceAttr(resourceName, "runtime.0.name", "APPSYNC_JS"), - resource.TestCheckResourceAttr(resourceName, "runtime.0.runtime_version", "1.0.0"), - ), - }, - }, - }) -} - func testAccResolver_syncConfig(t *testing.T) { var resolver1 appsync.Resolver rName := fmt.Sprintf("tfacctest%d", sdkacctest.RandInt()) @@ -495,24 +454,6 @@ EOF ` } -func testAccResolverConfig_code(rName, code string) string { - return acctest.ConfigCompose(testAccResolverConfig_base(rName), fmt.Sprintf(` -resource "aws_appsync_resolver" "test" { - api_id = aws_appsync_graphql_api.test.id - field = "singlePost" - type = "Query" - data_source = aws_appsync_datasource.test.name - - code = file("%[1]s") - - runtime { - name = "APPSYNC_JS" - runtime_version = "1.0.0" - } -} -`, code)) -} - func testAccResolverConfig_dataSource(rName string) string { return testAccResolverConfig_base(rName) + ` resource "aws_appsync_datasource" "test2" { diff --git a/website/docs/r/appsync_resolver.html.markdown b/website/docs/r/appsync_resolver.html.markdown index 19ec2c46459..49d034122a4 100644 --- a/website/docs/r/appsync_resolver.html.markdown +++ b/website/docs/r/appsync_resolver.html.markdown @@ -13,7 +13,7 @@ Provides an AppSync Resolver. ## Example Usage ```terraform -resource "aws_appsync_graphql_api" "example" { +resource "aws_appsync_graphql_api" "test" { authentication_type = "API_KEY" name = "tf-example" @@ -38,8 +38,8 @@ schema { EOF } -resource "aws_appsync_datasource" "example" { - api_id = aws_appsync_graphql_api.example.id +resource "aws_appsync_datasource" "test" { + api_id = aws_appsync_graphql_api.test.id name = "tf_example" type = "HTTP" @@ -49,11 +49,11 @@ resource "aws_appsync_datasource" "example" { } # UNIT type resolver (default) -resource "aws_appsync_resolver" "example" { - api_id = aws_appsync_graphql_api.example.id +resource "aws_appsync_resolver" "test" { + api_id = aws_appsync_graphql_api.test.id field = "singlePost" type = "Query" - data_source = aws_appsync_datasource.example.name + data_source = aws_appsync_datasource.test.name request_template = < Date: Fri, 2 Dec 2022 18:09:24 +0200 Subject: [PATCH 8/9] changelog --- .changelog/28057.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.changelog/28057.txt b/.changelog/28057.txt index a5551a0cf3d..4207aabddec 100644 --- a/.changelog/28057.txt +++ b/.changelog/28057.txt @@ -5,7 +5,3 @@ resource/aws_appsync_function: Add `runtime` and `code` arguments ```release-note:enhancement resource/aws_appsync_function: Make `request_mapping_template` and `response_mapping_template` Optional ``` - -```release-note:enhancement -resource/aws_appsync_resolver: Add `runtime` and `code` arguments -``` \ No newline at end of file From b249de86a5f4400e894c90b5297ace5130533197 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Fri, 2 Dec 2022 18:10:37 +0200 Subject: [PATCH 9/9] changelog --- internal/service/appsync/appsync_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/appsync/appsync_test.go b/internal/service/appsync/appsync_test.go index 7b0364f15dd..4bc16aabb41 100644 --- a/internal/service/appsync/appsync_test.go +++ b/internal/service/appsync/appsync_test.go @@ -69,7 +69,6 @@ func TestAccAppSync_serial(t *testing.T) { }, "Resolver": { "basic": testAccResolver_basic, - "code": testAccResolver_code, "disappears": testAccResolver_disappears, "dataSource": testAccResolver_dataSource, "DataSource_lambda": testAccResolver_DataSource_lambda,