From 14a78aa9cb5bcbba5219030877320fbdafd137e4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 3 Aug 2019 18:42:53 -0400 Subject: [PATCH] r/aws_appmesh_route: Initial support for retry policy. --- aws/resource_aws_appmesh_route.go | 113 +++++++++++++++++++++ aws/resource_aws_appmesh_route_test.go | 4 + website/docs/r/appmesh_route.html.markdown | 15 +++ 3 files changed, 132 insertions(+) diff --git a/aws/resource_aws_appmesh_route.go b/aws/resource_aws_appmesh_route.go index 32086c33c01..88c0fed1bee 100644 --- a/aws/resource_aws_appmesh_route.go +++ b/aws/resource_aws_appmesh_route.go @@ -206,6 +206,65 @@ func resourceAwsAppmeshRoute() *schema.Resource { }, }, }, + + "retry_policy": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_retry_events": { + Type: schema.TypeSet, + Optional: true, + MinItems: 0, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + + "max_retries": { + Type: schema.TypeInt, + Optional: true, + Default: 1, + }, + + // TODO The API default is 15000ms, but that cannot currently be expressed via 'Default:'. + // TODO The API always returns results as ms. Should the attribute be 'per_retry_timeout_millis'? + // TODO See https://github.com/aws/aws-app-mesh-roadmap/issues/7#issuecomment-518041427. + "per_retry_timeout": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "unit": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + appmesh.DurationUnitMs, + appmesh.DurationUnitS, + }, false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "tcp_retry_events": { + Type: schema.TypeSet, + Optional: true, + MinItems: 0, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + }, + }, + }, }, }, }, @@ -537,6 +596,41 @@ func expandAppmeshRouteSpec(vSpec []interface{}) *appmesh.RouteSpec { spec.HttpRoute.Match = httpRouteMatch } + + if vHttpRetryPolicy, ok := mHttpRoute["retry_policy"].([]interface{}); ok && len(vHttpRetryPolicy) > 0 && vHttpRetryPolicy[0] != nil { + httpRetryPolicy := &appmesh.HttpRetryPolicy{} + + mHttpRetryPolicy := vHttpRetryPolicy[0].(map[string]interface{}) + + if vMaxRetries, ok := mHttpRetryPolicy["max_retries"].(int); ok && vMaxRetries > 0 { + httpRetryPolicy.MaxRetries = aws.Int64(int64(vMaxRetries)) + } + + if vHttpRetryEvents, ok := mHttpRetryPolicy["http_retry_events"].(*schema.Set); ok && vHttpRetryEvents.Len() > 0 { + httpRetryPolicy.HttpRetryEvents = expandStringSet(vHttpRetryEvents) + } + + if vPerRetryTimeout, ok := mHttpRetryPolicy["per_retry_timeout"].([]interface{}); ok && len(vPerRetryTimeout) > 0 && vPerRetryTimeout[0] != nil { + perRetryTimeout := &appmesh.Duration{} + + mPerRetryTimeout := vPerRetryTimeout[0].(map[string]interface{}) + + if vUnit, ok := mPerRetryTimeout["unit"].(string); ok && vUnit != "" { + perRetryTimeout.Unit = aws.String(vUnit) + } + if vValue, ok := mPerRetryTimeout["value"].(int); ok && vValue > 0 { + perRetryTimeout.Value = aws.Int64(int64(vValue)) + } + + httpRetryPolicy.PerRetryTimeout = perRetryTimeout + } + + if vTcpRetryEvents, ok := mHttpRetryPolicy["tcp_retry_events"].(*schema.Set); ok && vTcpRetryEvents.Len() > 0 { + httpRetryPolicy.TcpRetryEvents = expandStringSet(vTcpRetryEvents) + } + + spec.HttpRoute.RetryPolicy = httpRetryPolicy + } } if vTcpRoute, ok := mSpec["tcp_route"].([]interface{}); ok && len(vTcpRoute) > 0 && vTcpRoute[0] != nil { @@ -648,6 +742,25 @@ func flattenAppmeshRouteSpec(spec *appmesh.RouteSpec) []interface{} { } } + if httpRetryPolicy := httpRoute.RetryPolicy; httpRetryPolicy != nil { + mHttpRetryPolicy := map[string]interface{}{ + "http_retry_events": flattenStringSet(httpRetryPolicy.HttpRetryEvents), + "max_retries": int(aws.Int64Value(httpRetryPolicy.MaxRetries)), + "tcp_retry_events": flattenStringSet(httpRetryPolicy.TcpRetryEvents), + } + + if perRetryTimeout := httpRetryPolicy.PerRetryTimeout; perRetryTimeout != nil { + mPerRetryTimeout := map[string]interface{}{ + "unit": aws.StringValue(perRetryTimeout.Unit), + "value": int(aws.Int64Value(perRetryTimeout.Value)), + } + + mHttpRetryPolicy["per_retry_timeout"] = []interface{}{mPerRetryTimeout} + } + + mHttpRoute["retry_policy"] = []interface{}{mHttpRetryPolicy} + } + mSpec["http_route"] = []interface{}{mHttpRoute} } diff --git a/aws/resource_aws_appmesh_route_test.go b/aws/resource_aws_appmesh_route_test.go index c91dfc92459..564848f4bc4 100644 --- a/aws/resource_aws_appmesh_route_test.go +++ b/aws/resource_aws_appmesh_route_test.go @@ -125,6 +125,7 @@ func testAccAwsAppmeshRoute_httpRoute(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.method", ""), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.prefix", "/"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.scheme", ""), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.retry_policy.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), @@ -147,6 +148,7 @@ func testAccAwsAppmeshRoute_httpRoute(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.method", ""), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.prefix", "/path"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.scheme", ""), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.retry_policy.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), @@ -192,6 +194,7 @@ func testAccAwsAppmeshRoute_httpHeader(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.method", "POST"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.prefix", "/"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.scheme", "http"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.retry_policy.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), @@ -227,6 +230,7 @@ func testAccAwsAppmeshRoute_httpHeader(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.method", "PUT"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.prefix", "/path"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.scheme", "https"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.retry_policy.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), diff --git a/website/docs/r/appmesh_route.html.markdown b/website/docs/r/appmesh_route.html.markdown index fd4293e5c29..7bb8a0c46b0 100644 --- a/website/docs/r/appmesh_route.html.markdown +++ b/website/docs/r/appmesh_route.html.markdown @@ -82,6 +82,7 @@ The `http_route` object supports the following: * `action` - (Required) The action to take if a match is determined. * `match` - (Required) The criteria for determining an HTTP request match. +* `retry_policy` - (Optional) The retry policy. The `tcp_route` object supports the following: @@ -100,6 +101,20 @@ This parameter must always start with /, which by itself matches all requests to * `method` - (Optional) The HTTP method with which to match requests. Valid values: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `CONNECT`, `OPTIONS`, `TRACE`, `PATCH`. * `scheme` - (Optional) The URL scheme with which to match requests. Valid values: `HTTP`, `HTTPS`. +The `retry_policy` object supports the following: + +* `http_retry_events` - (Optional) List of HTTP retry events. +* `max_retries` - (Optional) The maximum number of retries. Default is `1`. +* `per_retry_timeout` - (Optional) The per-retry timeout. Default is `15s`. +* `tcp_retry_events` - (Optional) List of TCP retry events. The only valid value is `connection-error`. + +You must specify at least one value for `http_retry_events`, or at least one value for `tcp_retry_events`. + +The `per_retry_timeout` object supports the following: + +* `unit` - (Required) Retry unit. Valid values: `ms`, `s`. +* `value` - (Required) Retry value. + The `weighted_target` object supports the following: * `virtual_node` - (Required) The virtual node to associate with the weighted target.