From 70d3d9fe0c54b06260862b56bcc7356510d93848 Mon Sep 17 00:00:00 2001 From: Anthony Wat Date: Fri, 26 Jul 2024 23:09:27 -0400 Subject: [PATCH] feat: Add enhanced_metrics_config config block for aws_appsync_graphql_api --- .changelog/38570.txt | 3 + internal/service/appsync/appsync_test.go | 1 + internal/service/appsync/graphql_api.go | 64 +++++++++++++++++++ internal/service/appsync/graphql_api_test.go | 60 +++++++++++++++++ .../docs/r/appsync_graphql_api.html.markdown | 58 ++++++++++------- 5 files changed, 163 insertions(+), 23 deletions(-) create mode 100644 .changelog/38570.txt diff --git a/.changelog/38570.txt b/.changelog/38570.txt new file mode 100644 index 00000000000..cf832f174f9 --- /dev/null +++ b/.changelog/38570.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_appsync_graphql_api: Add `enhanced_metrics_config` configuration block +``` \ No newline at end of file diff --git a/internal/service/appsync/appsync_test.go b/internal/service/appsync/appsync_test.go index a25ca0d604e..2f91b582439 100644 --- a/internal/service/appsync/appsync_test.go +++ b/internal/service/appsync/appsync_test.go @@ -45,6 +45,7 @@ func TestAccAppSync_serial(t *testing.T) { "AuthenticationType_amazonCognitoUserPools": testAccGraphQLAPI_AuthenticationType_amazonCognitoUserPools, "AuthenticationType_openIDConnect": testAccGraphQLAPI_AuthenticationType_openIDConnect, "AuthenticationType_awsLambda": testAccGraphQLAPI_AuthenticationType_lambda, + "enhancedMetricsConfig": testAccGraphQLAPI_enhancedMetricsConfig, "log": testAccGraphQLAPI_log, "Log_fieldLogLevel": testAccGraphQLAPI_Log_fieldLogLevel, "Log_excludeVerboseContent": testAccGraphQLAPI_Log_excludeVerboseContent, diff --git a/internal/service/appsync/graphql_api.go b/internal/service/appsync/graphql_api.go index f5cc5f6315c..e53e2e60076 100644 --- a/internal/service/appsync/graphql_api.go +++ b/internal/service/appsync/graphql_api.go @@ -140,6 +140,30 @@ func resourceGraphQLAPI() *schema.Resource { Required: true, ValidateDiagFunc: enum.Validate[awstypes.AuthenticationType](), }, + "enhanced_metrics_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "data_source_level_metrics_behavior": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.DataSourceLevelMetricsBehavior](), + }, + "operation_level_metrics_config": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.OperationLevelMetricsConfig](), + }, + "resolver_level_metrics_behavior": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.ResolverLevelMetricsBehavior](), + }, + }, + }, + }, "introspection_config": { Type: schema.TypeString, Optional: true, @@ -305,6 +329,10 @@ func resourceGraphQLAPICreate(ctx context.Context, d *schema.ResourceData, meta input.AdditionalAuthenticationProviders = expandAdditionalAuthenticationProviders(v.([]interface{}), meta.(*conns.AWSClient).Region) } + if v, ok := d.GetOk("enhanced_metrics_config"); ok { + input.EnhancedMetricsConfig = expandEnhancedMetricsConfig(v.([]interface{})) + } + if v, ok := d.GetOk("introspection_config"); ok { input.IntrospectionConfig = awstypes.GraphQLApiIntrospectionConfig(v.(string)) } @@ -379,6 +407,9 @@ func resourceGraphQLAPIRead(ctx context.Context, d *schema.ResourceData, meta in } d.Set(names.AttrARN, api.Arn) d.Set("authentication_type", api.AuthenticationType) + if err := d.Set("enhanced_metrics_config", flattenEnhancedMetricsConfig(api.EnhancedMetricsConfig)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting enhanced_metrics_config: %s", err) + } d.Set("introspection_config", api.IntrospectionConfig) if err := d.Set("lambda_authorizer_config", flattenLambdaAuthorizerConfig(api.LambdaAuthorizerConfig)); err != nil { return sdkdiag.AppendErrorf(diags, "setting lambda_authorizer_config: %s", err) @@ -419,6 +450,10 @@ func resourceGraphQLAPIUpdate(ctx context.Context, d *schema.ResourceData, meta input.AdditionalAuthenticationProviders = expandAdditionalAuthenticationProviders(v.([]interface{}), meta.(*conns.AWSClient).Region) } + if v, ok := d.GetOk("enhanced_metrics_config"); ok { + input.EnhancedMetricsConfig = expandEnhancedMetricsConfig(v.([]interface{})) + } + if v, ok := d.GetOk("introspection_config"); ok { input.IntrospectionConfig = awstypes.GraphQLApiIntrospectionConfig(v.(string)) } @@ -655,6 +690,21 @@ func expandUserPoolConfig(tfList []interface{}, currentRegion string) *awstypes. return apiObject } +func expandEnhancedMetricsConfig(tfList []interface{}) *awstypes.EnhancedMetricsConfig { + if len(tfList) < 1 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + apiObject := &awstypes.EnhancedMetricsConfig{ + DataSourceLevelMetricsBehavior: awstypes.DataSourceLevelMetricsBehavior(tfMap["data_source_level_metrics_behavior"].(string)), + OperationLevelMetricsConfig: awstypes.OperationLevelMetricsConfig(tfMap["operation_level_metrics_config"].(string)), + ResolverLevelMetricsBehavior: awstypes.ResolverLevelMetricsBehavior(tfMap["resolver_level_metrics_behavior"].(string)), + } + + return apiObject +} + func expandLambdaAuthorizerConfig(tfList []interface{}) *awstypes.LambdaAuthorizerConfig { if len(tfList) < 1 || tfList[0] == nil { return nil @@ -776,6 +826,20 @@ func flattenUserPoolConfig(apiObject *awstypes.UserPoolConfig) []interface{} { return []interface{}{tfMap} } +func flattenEnhancedMetricsConfig(apiObject *awstypes.EnhancedMetricsConfig) []interface{} { + if apiObject == nil { + return []interface{}{} + } + + tfMap := map[string]interface{}{ + "data_source_level_metrics_behavior": apiObject.DataSourceLevelMetricsBehavior, + "operation_level_metrics_config": apiObject.OperationLevelMetricsConfig, + "resolver_level_metrics_behavior": apiObject.ResolverLevelMetricsBehavior, + } + + return []interface{}{tfMap} +} + func flattenLambdaAuthorizerConfig(apiObject *awstypes.LambdaAuthorizerConfig) []interface{} { if apiObject == nil { return []interface{}{} diff --git a/internal/service/appsync/graphql_api_test.go b/internal/service/appsync/graphql_api_test.go index cf2ddcd7a0a..8f8088d5874 100644 --- a/internal/service/appsync/graphql_api_test.go +++ b/internal/service/appsync/graphql_api_test.go @@ -326,6 +326,52 @@ func testAccGraphQLAPI_AuthenticationType_lambda(t *testing.T) { }) } +func testAccGraphQLAPI_enhancedMetricsConfig(t *testing.T) { + ctx := acctest.Context(t) + var api1 awstypes.GraphqlApi + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_appsync_graphql_api.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.AppSyncEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.AppSyncServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGraphQLAPIDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGraphQLAPIConfig_enhancedMetricsConfig(rName, "PER_DATA_SOURCE_METRICS", "ENABLED", "PER_RESOLVER_METRICS"), + Check: resource.ComposeTestCheckFunc( + testAccCheckGraphQLAPIExists(ctx, resourceName, &api1), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.0.data_source_level_metrics_behavior", "PER_DATA_SOURCE_METRICS"), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.0.operation_level_metrics_config", "ENABLED"), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.0.resolver_level_metrics_behavior", "PER_RESOLVER_METRICS"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGraphQLAPIConfig_enhancedMetricsConfig(rName, "FULL_REQUEST_DATA_SOURCE_METRICS", "DISABLED", "FULL_REQUEST_RESOLVER_METRICS"), + Check: resource.ComposeTestCheckFunc( + testAccCheckGraphQLAPIExists(ctx, resourceName, &api1), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.0.data_source_level_metrics_behavior", "FULL_REQUEST_DATA_SOURCE_METRICS"), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.0.operation_level_metrics_config", "DISABLED"), + resource.TestCheckResourceAttr(resourceName, "enhanced_metrics_config.0.resolver_level_metrics_behavior", "FULL_REQUEST_RESOLVER_METRICS"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccGraphQLAPI_log(t *testing.T) { ctx := acctest.Context(t) var api1 awstypes.GraphqlApi @@ -1376,6 +1422,20 @@ resource "aws_appsync_graphql_api" "test" { `, rName, visibility) } +func testAccGraphQLAPIConfig_enhancedMetricsConfig(rName, dataSourceLevelMetricsBehavior, operationLevelMetricsConfig, resolverLevelMetricsBehavior string) string { + return fmt.Sprintf(` +resource "aws_appsync_graphql_api" "test" { + authentication_type = "API_KEY" + name = %[1]q + enhanced_metrics_config { + data_source_level_metrics_behavior = %[2]q + operation_level_metrics_config = %[3]q + resolver_level_metrics_behavior = %[4]q + } +} +`, rName, dataSourceLevelMetricsBehavior, operationLevelMetricsConfig, resolverLevelMetricsBehavior) +} + func testAccGraphQLAPIConfig_logFieldLogLevel(rName, fieldLogLevel string) string { return fmt.Sprintf(` data "aws_partition" "current" {} diff --git a/website/docs/r/appsync_graphql_api.html.markdown b/website/docs/r/appsync_graphql_api.html.markdown index bc6c1baf08f..9928be40255 100644 --- a/website/docs/r/appsync_graphql_api.html.markdown +++ b/website/docs/r/appsync_graphql_api.html.markdown @@ -212,32 +212,28 @@ resource "aws_appsync_graphql_api" "example" { ## Argument Reference -This resource supports the following arguments: +The following arguments are required: * `authentication_type` - (Required) Authentication type. Valid values: `API_KEY`, `AWS_IAM`, `AMAZON_COGNITO_USER_POOLS`, `OPENID_CONNECT`, `AWS_LAMBDA` * `name` - (Required) User-supplied name for the GraphSQL API. -* `log_config` - (Optional) Nested argument containing logging configuration. See [`log_config` Block](#log_config-block) for details. -* `openid_connect_config` - (Optional) Nested argument containing OpenID Connect configuration. See [`openid_connect_config` Block](#openid_connect_config-block) for details. -* `user_pool_config` - (Optional) Amazon Cognito User Pool configuration. See [`user_pool_config` Block](#user_pool_config-block) for details. -* `lambda_authorizer_config` - (Optional) Nested argument containing Lambda authorizer configuration. See [`lambda_authorizer_config` Block](#lambda_authorizer_config-block) for details. -* `schema` - (Optional) Schema definition, in GraphQL schema language format. Terraform cannot perform drift detection of this configuration. + +The following arguments are optional: + * `additional_authentication_provider` - (Optional) One or more additional authentication providers for the GraphSQL API. See [`additional_authentication_provider` Block](#additional_authentication_provider-block) for details. +* `enhanced_metrics_config` - (Optional) Enables and controls the enhanced metrics feature. See [`enhanced_metrics_config` Block](#enhanced_metrics_config-block) for details. * `introspection_config` - (Optional) Sets the value of the GraphQL API to enable (`ENABLED`) or disable (`DISABLED`) introspection. If no value is provided, the introspection configuration will be set to ENABLED by default. This field will produce an error if the operation attempts to use the introspection feature while this field is disabled. For more information about introspection, see [GraphQL introspection](https://graphql.org/learn/introspection/). +* `lambda_authorizer_config` - (Optional) Nested argument containing Lambda authorizer configuration. See [`lambda_authorizer_config` Block](#lambda_authorizer_config-block) for details. +* `log_config` - (Optional) Nested argument containing logging configuration. See [`log_config` Block](#log_config-block) for details. +* `openid_connect_config` - (Optional) Nested argument containing OpenID Connect configuration. See [`openid_connect_config` Block](#openid_connect_config-block) for details. * `query_depth_limit` - (Optional) The maximum depth a query can have in a single request. Depth refers to the amount of nested levels allowed in the body of query. The default value is `0` (or unspecified), which indicates there's no depth limit. If you set a limit, it can be between `1` and `75` nested levels. This field will produce a limit error if the operation falls out of bounds. Note that fields can still be set to nullable or non-nullable. If a non-nullable field produces an error, the error will be thrown upwards to the first nullable field available. * `resolver_count_limit` - (Optional) The maximum number of resolvers that can be invoked in a single request. The default value is `0` (or unspecified), which will set the limit to `10000`. When specified, the limit value can be between `1` and `10000`. This field will produce a limit error if the operation falls out of bounds. +* `schema` - (Optional) Schema definition, in GraphQL schema language format. Terraform cannot perform drift detection of this configuration. * `tags` - (Optional) Map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. -* `xray_enabled` - (Optional) Whether tracing with X-ray is enabled. Defaults to false. +* `user_pool_config` - (Optional) Amazon Cognito User Pool configuration. See [`user_pool_config` Block](#user_pool_config-block) for details. * `visibility` - (Optional) Sets the value of the GraphQL API to public (`GLOBAL`) or private (`PRIVATE`). If no value is provided, the visibility will be set to `GLOBAL` by default. This value cannot be changed once the API has been created. - -### `log_config` Block - -The `log_config` configuration block supports the following arguments: - -* `cloudwatch_logs_role_arn` - (Required) Amazon Resource Name of the service role that AWS AppSync will assume to publish to Amazon CloudWatch logs in your account. -* `field_log_level` - (Required) Field logging level. Valid values: `ALL`, `ERROR`, `NONE`. -* `exclude_verbose_content` - (Optional) Set to TRUE to exclude sections that contain information such as headers, context, and evaluated mapping templates, regardless of logging level. Valid values: `true`, `false`. Default value: `false` +* `xray_enabled` - (Optional) Whether tracing with X-ray is enabled. Defaults to false. ### `additional_authentication_provider` Block @@ -247,6 +243,30 @@ The `additional_authentication_provider` configuration block supports the follow * `openid_connect_config` - (Optional) Nested argument containing OpenID Connect configuration. See [`openid_connect_config` Block](#openid_connect_config-block) for details. * `user_pool_config` - (Optional) Amazon Cognito User Pool configuration. See [`user_pool_config` Block](#user_pool_config-block) for details. +### `enhanced_metrics_config` Block + +The `enhanced_metrics_config` configuration block supports the following arguments. See [EnhancedMetricsConfig](https://docs.aws.amazon.com/appsync/latest/APIReference/API_EnhancedMetricsConfig.html) for more information. + +* `data_source_level_metrics_behavior` - (Optional) How data source metrics will be emitted to CloudWatch. Valid values: `FULL_REQUEST_DATA_SOURCE_METRICS`, `PER_DATA_SOURCE_METRICS` +* `operation_level_metrics_config` - (Optional) How operation metrics will be emitted to CloudWatch. Valid values: `ENABLED`, `DISABLED` +* `resolver_level_metrics_behavior` - (Optional) How resolver metrics will be emitted to CloudWatch. Valid values: `FULL_REQUEST_RESOLVER_METRICS`, `PER_RESOLVER_METRICS` + +### `lambda_authorizer_config` Block + +The `lambda_authorizer_config` configuration block supports the following arguments: + +* `authorizer_uri` - (Required) ARN of the Lambda function to be called for authorization. Note: This Lambda function must have a resource-based policy assigned to it, to allow `lambda:InvokeFunction` from service principal `appsync.amazonaws.com`. +* `authorizer_result_ttl_in_seconds` - (Optional) Number of seconds a response should be cached for. The default is 5 minutes (300 seconds). The Lambda function can override this by returning a `ttlOverride` key in its response. A value of 0 disables caching of responses. Minimum value of 0. Maximum value of 3600. +* `identity_validation_expression` - (Optional) Regular expression for validation of tokens before the Lambda function is called. + +### `log_config` Block + +The `log_config` configuration block supports the following arguments: + +* `cloudwatch_logs_role_arn` - (Required) Amazon Resource Name of the service role that AWS AppSync will assume to publish to Amazon CloudWatch logs in your account. +* `field_log_level` - (Required) Field logging level. Valid values: `ALL`, `ERROR`, `NONE`. +* `exclude_verbose_content` - (Optional) Set to TRUE to exclude sections that contain information such as headers, context, and evaluated mapping templates, regardless of logging level. Valid values: `true`, `false`. Default value: `false` + ### `openid_connect_config` Block The `openid_connect_config` configuration block supports the following arguments: @@ -265,14 +285,6 @@ The `user_pool_config` configuration block supports the following arguments: * `app_id_client_regex` - (Optional) Regular expression for validating the incoming Amazon Cognito User Pool app client ID. * `aws_region` - (Optional) AWS region in which the user pool was created. -### `lambda_authorizer_config` Block - -The `lambda_authorizer_config` configuration block supports the following arguments: - -* `authorizer_uri` - (Required) ARN of the Lambda function to be called for authorization. Note: This Lambda function must have a resource-based policy assigned to it, to allow `lambda:InvokeFunction` from service principal `appsync.amazonaws.com`. -* `authorizer_result_ttl_in_seconds` - (Optional) Number of seconds a response should be cached for. The default is 5 minutes (300 seconds). The Lambda function can override this by returning a `ttlOverride` key in its response. A value of 0 disables caching of responses. Minimum value of 0. Maximum value of 3600. -* `identity_validation_expression` - (Optional) Regular expression for validation of tokens before the Lambda function is called. - ## Attribute Reference This resource exports the following attributes in addition to the arguments above: