diff --git a/aws/resource_aws_appmesh_route.go b/aws/resource_aws_appmesh_route.go index 5419b31f7e9f..5e02abfa7a4c 100644 --- a/aws/resource_aws_appmesh_route.go +++ b/aws/resource_aws_appmesh_route.go @@ -185,6 +185,11 @@ func resourceAwsAppmeshRoute() *schema.Resource { }, "method_name": { + Type: schema.TypeString, + Optional: true, + }, + + "prefix": { Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringLenBetween(0, 50), @@ -257,6 +262,58 @@ func resourceAwsAppmeshRoute() *schema.Resource { }, }, }, + + "timeout": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "per_request": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -318,6 +375,37 @@ func resourceAwsAppmeshRoute() *schema.Resource { }, }, }, + + "timeout": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -546,6 +634,58 @@ func appmeshRouteHttpRouteSchema() *schema.Schema { }, }, }, + + "timeout": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "per_request": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, }, }, } diff --git a/aws/resource_aws_appmesh_route_test.go b/aws/resource_aws_appmesh_route_test.go index f9583f18d4f4..60eea6696dbb 100644 --- a/aws/resource_aws_appmesh_route_test.go +++ b/aws/resource_aws_appmesh_route_test.go @@ -146,6 +146,7 @@ func testAccAwsAppmeshRoute_grpcRoute(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.per_retry_timeout.0.unit", "s"), resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.per_retry_timeout.0.value", "15"), resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.tcp_retry_events.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), @@ -197,6 +198,7 @@ func testAccAwsAppmeshRoute_grpcRoute(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.per_retry_timeout.0.value", "250000"), resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.tcp_retry_events.#", "1"), tfawsresource.TestCheckTypeSetElemAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.tcp_retry_events.*", "connection-error"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), @@ -248,6 +250,105 @@ func testAccAwsAppmeshRoute_grpcRoute(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.per_retry_timeout.0.value", "250000"), resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.tcp_retry_events.#", "1"), tfawsresource.TestCheckTypeSetElemAttr(resourceName, "spec.0.grpc_route.0.retry_policy.0.tcp_retry_events.*", "connection-error"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccAwsAppmeshRouteImportStateIdFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccAwsAppmeshRoute_grpcRouteTimeout(t *testing.T) { + var r appmesh.RouteData + resourceName := "aws_appmesh_route.test" + meshName := acctest.RandomWithPrefix("tf-acc-test") + vrName := acctest.RandomWithPrefix("tf-acc-test") + vn1Name := acctest.RandomWithPrefix("tf-acc-test") + vn2Name := acctest.RandomWithPrefix("tf-acc-test") + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppmeshRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsAppmeshRouteConfig_grpcRouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.metadata.#", "1"), + tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "spec.0.grpc_route.0.match.0.metadata.*", map[string]string{ + "invert": "false", + "match.#": "0", + "name": "X-Testing1", + }), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.method_name", ""), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.service_name", ""), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.idle.0.unit", "ms"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.idle.0.value", "250000"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.per_request.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + Config: testAccAwsAppmeshRouteConfig_grpcRouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.metadata.#", "1"), + tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "spec.0.grpc_route.0.match.0.metadata.*", map[string]string{ + "invert": "false", + "match.#": "0", + "name": "X-Testing1", + }), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.method_name", ""), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.service_name", ""), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.idle.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.idle.0.value", "10"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.per_request.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.per_request.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.0.per_request.0.value", "5"), resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), @@ -313,6 +414,7 @@ func testAccAwsAppmeshRoute_http2Route(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.retry_policy.0.per_retry_timeout.0.unit", "s"), resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.retry_policy.0.per_retry_timeout.0.value", "15"), resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.retry_policy.0.tcp_retry_events.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), @@ -363,6 +465,109 @@ func testAccAwsAppmeshRoute_http2Route(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.retry_policy.0.per_retry_timeout.0.value", "250000"), resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.retry_policy.0.tcp_retry_events.#", "1"), tfawsresource.TestCheckTypeSetElemAttr(resourceName, "spec.0.http2_route.0.retry_policy.0.tcp_retry_events.*", "connection-error"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccAwsAppmeshRouteImportStateIdFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccAwsAppmeshRoute_http2RouteTimeout(t *testing.T) { + var r appmesh.RouteData + resourceName := "aws_appmesh_route.test" + meshName := acctest.RandomWithPrefix("tf-acc-test") + vrName := acctest.RandomWithPrefix("tf-acc-test") + vn1Name := acctest.RandomWithPrefix("tf-acc-test") + vn2Name := acctest.RandomWithPrefix("tf-acc-test") + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppmeshRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsAppmeshRouteConfig_http2RouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.header.#", "1"), + tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "spec.0.http2_route.0.match.0.header.*", map[string]string{ + "invert": "false", + "match.#": "0", + "name": "X-Testing1", + }), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.method", "POST"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.prefix", "/"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.scheme", "http"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.retry_policy.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.idle.0.unit", "ms"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.idle.0.value", "250000"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.per_request.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + Config: testAccAwsAppmeshRouteConfig_http2RouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.header.#", "1"), + tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "spec.0.http2_route.0.match.0.header.*", map[string]string{ + "invert": "false", + "match.#": "0", + "name": "X-Testing1", + }), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.method", "POST"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.prefix", "/"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.match.0.scheme", "http"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.retry_policy.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.idle.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.idle.0.value", "10"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.per_request.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.per_request.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.0.timeout.0.per_request.0.value", "5"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), @@ -416,6 +621,7 @@ func testAccAwsAppmeshRoute_httpRoute(t *testing.T) { 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.http_route.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), @@ -445,6 +651,7 @@ func testAccAwsAppmeshRoute_httpRoute(t *testing.T) { 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.http_route.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), @@ -471,6 +678,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.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), @@ -489,6 +697,100 @@ func testAccAwsAppmeshRoute_httpRoute(t *testing.T) { }) } +func testAccAwsAppmeshRoute_httpRouteTimeout(t *testing.T) { + var r appmesh.RouteData + resourceName := "aws_appmesh_route.test" + meshName := acctest.RandomWithPrefix("tf-acc-test") + vrName := acctest.RandomWithPrefix("tf-acc-test") + vn1Name := acctest.RandomWithPrefix("tf-acc-test") + vn2Name := acctest.RandomWithPrefix("tf-acc-test") + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppmeshRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAppmeshRouteConfig_httpRouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.header.#", "0"), + 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.http_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.idle.0.unit", "ms"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.idle.0.value", "250000"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.per_request.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + Config: testAccAppmeshRouteConfig_httpRouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.match.0.header.#", "0"), + 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.http_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.idle.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.idle.0.value", "10"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.per_request.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.per_request.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.0.timeout.0.per_request.0.value", "5"), + resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccAwsAppmeshRouteImportStateIdFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccAwsAppmeshRoute_tcpRoute(t *testing.T) { var r appmesh.RouteData resourceName := "aws_appmesh_route.test" @@ -519,6 +821,31 @@ func testAccAwsAppmeshRoute_tcpRoute(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + Config: testAccAppmeshRouteConfig_tcpRouteUpdated(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.0.weighted_target.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), @@ -527,7 +854,52 @@ func testAccAwsAppmeshRoute_tcpRoute(t *testing.T) { ), }, { - Config: testAccAppmeshRouteConfig_tcpRouteUpdated(meshName, vrName, vn1Name, vn2Name, rName), + Config: testAccAppmeshRouteConfig_tcpRouteUpdatedWithZeroWeight(meshName, vrName, vn1Name, vn2Name, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshRouteExists(resourceName, &r), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.0.weighted_target.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.#", "0"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccAwsAppmeshRouteImportStateIdFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccAwsAppmeshRoute_tcpRouteTimeout(t *testing.T) { + var r appmesh.RouteData + resourceName := "aws_appmesh_route.test" + meshName := acctest.RandomWithPrefix("tf-acc-test") + vrName := acctest.RandomWithPrefix("tf-acc-test") + vn1Name := acctest.RandomWithPrefix("tf-acc-test") + vn2Name := acctest.RandomWithPrefix("tf-acc-test") + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppmeshRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAppmeshRouteConfig_tcpRouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName), Check: resource.ComposeTestCheckFunc( testAccCheckAppmeshRouteExists(resourceName, &r), resource.TestCheckResourceAttr(resourceName, "name", rName), @@ -541,7 +913,11 @@ func testAccAwsAppmeshRoute_tcpRoute(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.#", "1"), - resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.0.weighted_target.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.0.idle.0.unit", "ms"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.0.idle.0.value", "250000"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), @@ -550,7 +926,7 @@ func testAccAwsAppmeshRoute_tcpRoute(t *testing.T) { ), }, { - Config: testAccAppmeshRouteConfig_tcpRouteUpdatedWithZeroWeight(meshName, vrName, vn1Name, vn2Name, rName), + Config: testAccAppmeshRouteConfig_tcpRouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName), Check: resource.ComposeTestCheckFunc( testAccCheckAppmeshRouteExists(resourceName, &r), resource.TestCheckResourceAttr(resourceName, "name", rName), @@ -558,11 +934,18 @@ func testAccAwsAppmeshRoute_tcpRoute(t *testing.T) { testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName), resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.priority", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.#", "1"), - resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.0.weighted_target.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.action.0.weighted_target.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.0.idle.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.0.timeout.0.idle.0.value", "10"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), @@ -1190,6 +1573,79 @@ resource "aws_appmesh_route" "test" { `, rName)) } +func testAccAwsAppmeshRouteConfig_grpcRouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "grpc", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + grpc_route { + match { + metadata { + name = "X-Testing1" + } + } + + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "ms" + value = 250000 + } + } + } + } +} +`, rName)) +} + +func testAccAwsAppmeshRouteConfig_grpcRouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "grpc", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + grpc_route { + match { + metadata { + name = "X-Testing1" + } + } + + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "s" + value = 10 + } + + per_request { + unit = "s" + value = 5 + } + } + } + } +} +`, rName)) +} + func testAccAwsAppmeshRouteConfig_http2Route(meshName, vrName, vn1Name, vn2Name, rName string) string { return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http2", vn1Name, vn2Name), fmt.Sprintf(` resource "aws_appmesh_route" "test" { @@ -1296,6 +1752,87 @@ resource "aws_appmesh_route" "test" { `, rName)) } +func testAccAwsAppmeshRouteConfig_http2RouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http2", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + http2_route { + match { + prefix = "/" + method = "POST" + scheme = "http" + + header { + name = "X-Testing1" + } + } + + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "ms" + value = 250000 + } + } + } + } +} +`, rName)) +} + +func testAccAwsAppmeshRouteConfig_http2RouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http2", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + http2_route { + match { + prefix = "/" + method = "POST" + scheme = "http" + + header { + name = "X-Testing1" + } + } + + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "s" + value = 10 + } + + per_request { + unit = "s" + value = 5 + } + } + } + } +} +`, rName)) +} + func testAccAppmeshRouteConfig_httpRoute(meshName, vrName, vn1Name, vn2Name, rName string) string { return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http", vn1Name, vn2Name), fmt.Sprintf(` resource "aws_appmesh_route" "test" { @@ -1381,6 +1918,75 @@ resource "aws_appmesh_route" "test" { `, rName)) } +func testAccAppmeshRouteConfig_httpRouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + http_route { + match { + prefix = "/" + } + + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "ms" + value = 250000 + } + } + } + } +} +`, rName)) +} + +func testAccAppmeshRouteConfig_httpRouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + http_route { + match { + prefix = "/" + } + + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "s" + value = 10 + } + + per_request { + unit = "s" + value = 5 + } + } + } + } +} +`, rName)) +} + func testAccAppmeshRouteConfig_tcpRoute(meshName, vrName, vn1Name, vn2Name, rName string) string { return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "tcp", vn1Name, vn2Name), fmt.Sprintf(` resource "aws_appmesh_route" "test" { @@ -1454,6 +2060,62 @@ resource "aws_appmesh_route" "test" { `, rName)) } +func testAccAppmeshRouteConfig_tcpRouteWithTimeout(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "tcp", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + tcp_route { + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "ms" + value = 250000 + } + } + } + } +} +`, rName)) +} + +func testAccAppmeshRouteConfig_tcpRouteWithTimeoutUpdated(meshName, vrName, vn1Name, vn2Name, rName string) string { + return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "tcp", vn1Name, vn2Name), fmt.Sprintf(` +resource "aws_appmesh_route" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + virtual_router_name = aws_appmesh_virtual_router.test.name + + spec { + tcp_route { + action { + weighted_target { + virtual_node = aws_appmesh_virtual_node.foo.name + weight = 100 + } + } + + timeout { + idle { + unit = "s" + value = 10 + } + } + } + } +} +`, rName)) +} + func testAccAppmeshRouteConfigWithTags(meshName, vrName, vn1Name, vn2Name, rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http", vn1Name, vn2Name), fmt.Sprintf(` resource "aws_appmesh_route" "test" { diff --git a/aws/resource_aws_appmesh_test.go b/aws/resource_aws_appmesh_test.go index 023035297cf8..5b8c18b44b60 100644 --- a/aws/resource_aws_appmesh_test.go +++ b/aws/resource_aws_appmesh_test.go @@ -12,14 +12,18 @@ func TestAccAWSAppmesh_serial(t *testing.T) { "tags": testAccAwsAppmeshMesh_tags, }, "Route": { - "grpcRoute": testAccAwsAppmeshRoute_grpcRoute, - "http2Route": testAccAwsAppmeshRoute_http2Route, - "httpHeader": testAccAwsAppmeshRoute_httpHeader, - "httpRetryPolicy": testAccAwsAppmeshRoute_httpRetryPolicy, - "httpRoute": testAccAwsAppmeshRoute_httpRoute, - "routePriority": testAccAwsAppmeshRoute_routePriority, - "tcpRoute": testAccAwsAppmeshRoute_tcpRoute, - "tags": testAccAwsAppmeshRoute_tags, + "grpcRoute": testAccAwsAppmeshRoute_grpcRoute, + "grpcRouteTimeout": testAccAwsAppmeshRoute_grpcRouteTimeout, + "http2Route": testAccAwsAppmeshRoute_http2Route, + "http2RouteTimeout": testAccAwsAppmeshRoute_http2RouteTimeout, + "httpHeader": testAccAwsAppmeshRoute_httpHeader, + "httpRetryPolicy": testAccAwsAppmeshRoute_httpRetryPolicy, + "httpRoute": testAccAwsAppmeshRoute_httpRoute, + "httpRouteTimeout": testAccAwsAppmeshRoute_httpRouteTimeout, + "routePriority": testAccAwsAppmeshRoute_routePriority, + "tcpRoute": testAccAwsAppmeshRoute_tcpRoute, + "tcpRouteTimeout": testAccAwsAppmeshRoute_tcpRouteTimeout, + "tags": testAccAwsAppmeshRoute_tags, }, "VirtualNode": { "basic": testAccAwsAppmeshVirtualNode_basic, @@ -28,6 +32,7 @@ func TestAccAWSAppmesh_serial(t *testing.T) { "clientPolicyFile": testAccAwsAppmeshVirtualNode_clientPolicyFile, "cloudMapServiceDiscovery": testAccAwsAppmeshVirtualNode_cloudMapServiceDiscovery, "listenerHealthChecks": testAccAwsAppmeshVirtualNode_listenerHealthChecks, + "listenerTimeout": testAccAwsAppmeshVirtualNode_listenerTimeout, "logging": testAccAwsAppmeshVirtualNode_logging, "tls": testAccAwsAppmeshVirtualNode_tls, "tags": testAccAwsAppmeshVirtualNode_tags, diff --git a/aws/resource_aws_appmesh_virtual_node.go b/aws/resource_aws_appmesh_virtual_node.go index 81e3c8ff5561..db86d4a1a5ff 100644 --- a/aws/resource_aws_appmesh_virtual_node.go +++ b/aws/resource_aws_appmesh_virtual_node.go @@ -177,6 +177,203 @@ func resourceAwsAppmeshVirtualNode() *schema.Resource { }, }, + "timeout": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "grpc": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "per_request": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, + + "http": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "per_request": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, + + "http2": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "per_request": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, + + "tcp": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle": { + 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(appmesh.DurationUnit_Values(), false), + }, + + "value": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "tls": { Type: schema.TypeList, Optional: true, diff --git a/aws/resource_aws_appmesh_virtual_node_test.go b/aws/resource_aws_appmesh_virtual_node_test.go index 531de734a21e..0a5803aff448 100644 --- a/aws/resource_aws_appmesh_virtual_node_test.go +++ b/aws/resource_aws_appmesh_virtual_node_test.go @@ -146,7 +146,6 @@ func testAccAwsAppmeshVirtualNode_cloudMapServiceDiscovery(t *testing.T) { testAccCheckAppmeshVirtualNodeExists(resourceName, &vn), resource.TestCheckResourceAttr(resourceName, "name", vnName), resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), - testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.0.aws_cloud_map.#", "1"), @@ -162,7 +161,6 @@ func testAccAwsAppmeshVirtualNode_cloudMapServiceDiscovery(t *testing.T) { testAccCheckAppmeshVirtualNodeExists(resourceName, &vn), resource.TestCheckResourceAttr(resourceName, "name", vnName), resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), - testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.0.aws_cloud_map.#", "1"), @@ -220,6 +218,7 @@ func testAccAwsAppmeshVirtualNode_listenerHealthChecks(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.port", "8080"), resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.protocol", "grpc"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.tls.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.logging.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.#", "1"), @@ -262,6 +261,7 @@ func testAccAwsAppmeshVirtualNode_listenerHealthChecks(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.#", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.port", "8081"), resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.protocol", "http"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.tls.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.logging.#", "0"), resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.#", "1"), @@ -283,6 +283,100 @@ func testAccAwsAppmeshVirtualNode_listenerHealthChecks(t *testing.T) { }) } +func testAccAwsAppmeshVirtualNode_listenerTimeout(t *testing.T) { + var vn appmesh.VirtualNodeData + resourceName := "aws_appmesh_virtual_node.test" + meshName := acctest.RandomWithPrefix("tf-acc-test") + vnName := acctest.RandomWithPrefix("tf-acc-test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppmeshVirtualNodeDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAppmeshVirtualNodeConfig_listenerTimeout(meshName, vnName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshVirtualNodeExists(resourceName, &vn), + resource.TestCheckResourceAttr(resourceName, "name", vnName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.backend.#", "1"), + tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "spec.0.backend.*", map[string]string{ + "virtual_service.#": "1", + "virtual_service.0.virtual_service_name": "servicea.simpleapp.local", + }), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.port", "8080"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.protocol", "tcp"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.grpc.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http2.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.tcp.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.tcp.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.tcp.0.idle.0.unit", "ms"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.tcp.0.idle.0.value", "250000"), + resource.TestCheckResourceAttr(resourceName, "spec.0.logging.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.0.dns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.0.dns.0.hostname", "serviceb.simpleapp.local"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualNode/%s", meshName, vnName)), + ), + }, + { + Config: testAccAppmeshVirtualNodeConfig_listenerTimeoutUpdated(meshName, vnName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshVirtualNodeExists(resourceName, &vn), + resource.TestCheckResourceAttr(resourceName, "name", vnName), + resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName), + testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.backend.#", "1"), + tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "spec.0.backend.*", map[string]string{ + "virtual_service.#": "1", + "virtual_service.0.virtual_service_name": "servicea.simpleapp.local", + }), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.port", "8080"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.port_mapping.0.protocol", "http"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.grpc.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.0.idle.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.0.idle.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.0.idle.0.value", "10"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.0.per_request.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.0.per_request.0.unit", "s"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http.0.per_request.0.value", "5"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.http2.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.listener.0.timeout.0.tcp.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.logging.#", "0"), + resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.0.dns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.service_discovery.0.dns.0.hostname", "serviceb.simpleapp.local"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"), + testAccCheckResourceAttrAccountID(resourceName, "resource_owner"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualNode/%s", meshName, vnName)), + ), + }, + { + ResourceName: resourceName, + ImportStateId: fmt.Sprintf("%s/%s", meshName, vnName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccAwsAppmeshVirtualNode_logging(t *testing.T) { var vn appmesh.VirtualNodeData resourceName := "aws_appmesh_virtual_node.test" @@ -869,18 +963,18 @@ resource "aws_acm_certificate" "test" { } func testAccAppmeshVirtualNodeConfig_basic(meshName, vnName string) string { - return testAccAppmeshVirtualNodeConfig_mesh(meshName) + fmt.Sprintf(` + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` resource "aws_appmesh_virtual_node" "test" { name = %[1]q mesh_name = aws_appmesh_mesh.test.id spec {} } -`, vnName) +`, vnName)) } func testAccAppmeshVirtualNodeConfig_cloudMapServiceDiscovery(meshName, vnName, rName, attrKey, attrValue string) string { - return testAccAppmeshVirtualNodeConfig_mesh(meshName) + fmt.Sprintf(` + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` resource "aws_service_discovery_http_namespace" "test" { name = %[2]q } @@ -915,11 +1009,11 @@ resource "aws_appmesh_virtual_node" "test" { } } } -`, vnName, rName, attrKey, attrValue) +`, vnName, rName, attrKey, attrValue)) } func testAccAppmeshVirtualNodeConfig_listenerHealthChecks(meshName, vnName string) string { - return testAccAppmeshVirtualNodeConfig_mesh(meshName) + fmt.Sprintf(` + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` resource "aws_appmesh_virtual_node" "test" { name = %[1]q mesh_name = aws_appmesh_mesh.test.id @@ -954,11 +1048,11 @@ resource "aws_appmesh_virtual_node" "test" { } } } -`, vnName) +`, vnName)) } func testAccAppmeshVirtualNodeConfig_listenerHealthChecksUpdated(meshName, vnName string) string { - return testAccAppmeshVirtualNodeConfig_mesh(meshName) + fmt.Sprintf(` + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` resource "aws_appmesh_virtual_node" "test" { name = %[1]q mesh_name = aws_appmesh_mesh.test.id @@ -999,11 +1093,94 @@ resource "aws_appmesh_virtual_node" "test" { } } } -`, vnName) +`, vnName)) +} + +func testAccAppmeshVirtualNodeConfig_listenerTimeout(meshName, vnName string) string { + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` +resource "aws_appmesh_virtual_node" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + + spec { + backend { + virtual_service { + virtual_service_name = "servicea.simpleapp.local" + } + } + + listener { + port_mapping { + port = 8080 + protocol = "tcp" + } + + timeout { + tcp { + idle { + unit = "ms" + value = 250000 + } + } + } + } + + service_discovery { + dns { + hostname = "serviceb.simpleapp.local" + } + } + } +} +`, vnName)) +} + +func testAccAppmeshVirtualNodeConfig_listenerTimeoutUpdated(meshName, vnName string) string { + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` +resource "aws_appmesh_virtual_node" "test" { + name = %[1]q + mesh_name = aws_appmesh_mesh.test.id + + spec { + backend { + virtual_service { + virtual_service_name = "servicea.simpleapp.local" + } + } + + listener { + port_mapping { + port = 8080 + protocol = "http" + } + + timeout { + http { + idle { + unit = "s" + value = 10 + } + + per_request { + unit = "s" + value = 5 + } + } + } + } + + service_discovery { + dns { + hostname = "serviceb.simpleapp.local" + } + } + } +} +`, vnName)) } func testAccAppmeshVirtualNodeConfig_logging(meshName, vnName, path string) string { - return testAccAppmeshVirtualNodeConfig_mesh(meshName) + fmt.Sprintf(` + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` resource "aws_appmesh_virtual_node" "test" { name = %[1]q mesh_name = aws_appmesh_mesh.test.id @@ -1037,11 +1214,11 @@ resource "aws_appmesh_virtual_node" "test" { } } } -`, vnName, path) +`, vnName, path)) } func testAccAppmeshVirtualNodeConfig_tags(meshName, vnName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { - return testAccAppmeshVirtualNodeConfig_mesh(meshName) + fmt.Sprintf(` + return composeConfig(testAccAppmeshVirtualNodeConfig_mesh(meshName), fmt.Sprintf(` resource "aws_appmesh_virtual_node" "test" { name = %[1]q mesh_name = aws_appmesh_mesh.test.id @@ -1053,7 +1230,7 @@ resource "aws_appmesh_virtual_node" "test" { %[4]s = %[5]q } } -`, vnName, tagKey1, tagValue1, tagKey2, tagValue2) +`, vnName, tagKey1, tagValue1, tagKey2, tagValue2)) } func testAccAppmeshVirtualNodeConfig_tlsFile(meshName, vnName string) string { diff --git a/aws/structure.go b/aws/structure.go index 4faea1684b6a..c27082eb17b3 100644 --- a/aws/structure.go +++ b/aws/structure.go @@ -4883,6 +4883,30 @@ func expandAppmeshVirtualNodeSpec(vSpec []interface{}) *appmesh.VirtualNodeSpec listener.Tls = tls } + if vTimeout, ok := mListener["timeout"].([]interface{}); ok && len(vTimeout) > 0 && vTimeout[0] != nil { + mTimeout := vTimeout[0].(map[string]interface{}) + + listenerTimeout := &appmesh.ListenerTimeout{} + + if vGrpcTimeout, ok := mTimeout["grpc"].([]interface{}); ok { + listenerTimeout.Grpc = expandAppmeshGrpcTimeout(vGrpcTimeout) + } + + if vHttpTimeout, ok := mTimeout["http"].([]interface{}); ok { + listenerTimeout.Http = expandAppmeshHttpTimeout(vHttpTimeout) + } + + if vHttp2Timeout, ok := mTimeout["http2"].([]interface{}); ok { + listenerTimeout.Http2 = expandAppmeshHttpTimeout(vHttp2Timeout) + } + + if vTcpTimeout, ok := mTimeout["tcp"].([]interface{}); ok { + listenerTimeout.Tcp = expandAppmeshTcpTimeout(vTcpTimeout) + } + + listener.Timeout = listenerTimeout + } + listeners = append(listeners, listener) } @@ -5029,6 +5053,16 @@ func flattenAppmeshVirtualNodeSpec(spec *appmesh.VirtualNodeSpec) []interface{} mListener["port_mapping"] = []interface{}{mPortMapping} } + if listenerTimeout := listener.Timeout; listenerTimeout != nil { + mListenerTimeout := map[string]interface{}{ + "grpc": flattenAppmeshGrpcTimeout(listenerTimeout.Grpc), + "http": flattenAppmeshHttpTimeout(listenerTimeout.Http), + "http2": flattenAppmeshHttpTimeout(listenerTimeout.Http2), + "tcp": flattenAppmeshTcpTimeout(listenerTimeout.Tcp), + } + mListener["timeout"] = []interface{}{mListenerTimeout} + } + if tls := listener.Tls; tls != nil { mTls := map[string]interface{}{ "mode": aws.StringValue(tls.Mode), @@ -5528,9 +5562,55 @@ func expandAppmeshGrpcRoute(vGrpcRoute []interface{}) *appmesh.GrpcRoute { grpcRoute.RetryPolicy = grpcRetryPolicy } + if vGrpcTimeout, ok := mGrpcRoute["timeout"].([]interface{}); ok { + grpcRoute.Timeout = expandAppmeshGrpcTimeout(vGrpcTimeout) + } + return grpcRoute } +func expandAppmeshGrpcTimeout(vGrpcTimeout []interface{}) *appmesh.GrpcTimeout { + if len(vGrpcTimeout) == 0 || vGrpcTimeout[0] == nil { + return nil + } + + grpcTimeout := &appmesh.GrpcTimeout{} + + mGrpcTimeout := vGrpcTimeout[0].(map[string]interface{}) + + if vIdleTimeout, ok := mGrpcTimeout["idle"].([]interface{}); ok && len(vIdleTimeout) > 0 && vIdleTimeout[0] != nil { + idleTimeout := &appmesh.Duration{} + + mIdleTimeout := vIdleTimeout[0].(map[string]interface{}) + + if vUnit, ok := mIdleTimeout["unit"].(string); ok && vUnit != "" { + idleTimeout.Unit = aws.String(vUnit) + } + if vValue, ok := mIdleTimeout["value"].(int); ok && vValue > 0 { + idleTimeout.Value = aws.Int64(int64(vValue)) + } + + grpcTimeout.Idle = idleTimeout + } + + if vPerRequestTimeout, ok := mGrpcTimeout["per_request"].([]interface{}); ok && len(vPerRequestTimeout) > 0 && vPerRequestTimeout[0] != nil { + perRequestTimeout := &appmesh.Duration{} + + mPerRequestTimeout := vPerRequestTimeout[0].(map[string]interface{}) + + if vUnit, ok := mPerRequestTimeout["unit"].(string); ok && vUnit != "" { + perRequestTimeout.Unit = aws.String(vUnit) + } + if vValue, ok := mPerRequestTimeout["value"].(int); ok && vValue > 0 { + perRequestTimeout.Value = aws.Int64(int64(vValue)) + } + + grpcTimeout.PerRequest = perRequestTimeout + } + + return grpcTimeout +} + func expandAppmeshHttpRoute(vHttpRoute []interface{}) *appmesh.HttpRoute { if len(vHttpRoute) == 0 || vHttpRoute[0] == nil { return nil @@ -5673,9 +5753,55 @@ func expandAppmeshHttpRoute(vHttpRoute []interface{}) *appmesh.HttpRoute { httpRoute.RetryPolicy = httpRetryPolicy } + if vHttpTimeout, ok := mHttpRoute["timeout"].([]interface{}); ok { + httpRoute.Timeout = expandAppmeshHttpTimeout(vHttpTimeout) + } + return httpRoute } +func expandAppmeshHttpTimeout(vHttpTimeout []interface{}) *appmesh.HttpTimeout { + if len(vHttpTimeout) == 0 || vHttpTimeout[0] == nil { + return nil + } + + httpTimeout := &appmesh.HttpTimeout{} + + mHttpTimeout := vHttpTimeout[0].(map[string]interface{}) + + if vIdleTimeout, ok := mHttpTimeout["idle"].([]interface{}); ok && len(vIdleTimeout) > 0 && vIdleTimeout[0] != nil { + idleTimeout := &appmesh.Duration{} + + mIdleTimeout := vIdleTimeout[0].(map[string]interface{}) + + if vUnit, ok := mIdleTimeout["unit"].(string); ok && vUnit != "" { + idleTimeout.Unit = aws.String(vUnit) + } + if vValue, ok := mIdleTimeout["value"].(int); ok && vValue > 0 { + idleTimeout.Value = aws.Int64(int64(vValue)) + } + + httpTimeout.Idle = idleTimeout + } + + if vPerRequestTimeout, ok := mHttpTimeout["per_request"].([]interface{}); ok && len(vPerRequestTimeout) > 0 && vPerRequestTimeout[0] != nil { + perRequestTimeout := &appmesh.Duration{} + + mPerRequestTimeout := vPerRequestTimeout[0].(map[string]interface{}) + + if vUnit, ok := mPerRequestTimeout["unit"].(string); ok && vUnit != "" { + perRequestTimeout.Unit = aws.String(vUnit) + } + if vValue, ok := mPerRequestTimeout["value"].(int); ok && vValue > 0 { + perRequestTimeout.Value = aws.Int64(int64(vValue)) + } + + httpTimeout.PerRequest = perRequestTimeout + } + + return httpTimeout +} + func expandAppmeshTcpRoute(vTcpRoute []interface{}) *appmesh.TcpRoute { if len(vTcpRoute) == 0 || vTcpRoute[0] == nil { return nil @@ -5712,9 +5838,40 @@ func expandAppmeshTcpRoute(vTcpRoute []interface{}) *appmesh.TcpRoute { } } + if vTcpTimeout, ok := mTcpRoute["timeout"].([]interface{}); ok { + tcpRoute.Timeout = expandAppmeshTcpTimeout(vTcpTimeout) + } + return tcpRoute } +func expandAppmeshTcpTimeout(vTcpTimeout []interface{}) *appmesh.TcpTimeout { + if len(vTcpTimeout) == 0 || vTcpTimeout[0] == nil { + return nil + } + + tcpTimeout := &appmesh.TcpTimeout{} + + mTcpTimeout := vTcpTimeout[0].(map[string]interface{}) + + if vIdleTimeout, ok := mTcpTimeout["idle"].([]interface{}); ok && len(vIdleTimeout) > 0 && vIdleTimeout[0] != nil { + idleTimeout := &appmesh.Duration{} + + mIdleTimeout := vIdleTimeout[0].(map[string]interface{}) + + if vUnit, ok := mIdleTimeout["unit"].(string); ok && vUnit != "" { + idleTimeout.Unit = aws.String(vUnit) + } + if vValue, ok := mIdleTimeout["value"].(int); ok && vValue > 0 { + idleTimeout.Value = aws.Int64(int64(vValue)) + } + + tcpTimeout.Idle = idleTimeout + } + + return tcpTimeout +} + func flattenAppmeshRouteSpec(spec *appmesh.RouteSpec) []interface{} { if spec == nil { return []interface{}{} @@ -5820,9 +5977,39 @@ func flattenAppmeshGrpcRoute(grpcRoute *appmesh.GrpcRoute) []interface{} { mGrpcRoute["retry_policy"] = []interface{}{mGrpcRetryPolicy} } + mGrpcRoute["timeout"] = flattenAppmeshGrpcTimeout(grpcRoute.Timeout) + return []interface{}{mGrpcRoute} } +func flattenAppmeshGrpcTimeout(grpcTimeout *appmesh.GrpcTimeout) []interface{} { + if grpcTimeout == nil { + return []interface{}{} + } + + mGrpcTimeout := map[string]interface{}{} + + if idleTimeout := grpcTimeout.Idle; idleTimeout != nil { + mIdleTimeout := map[string]interface{}{ + "unit": aws.StringValue(idleTimeout.Unit), + "value": int(aws.Int64Value(idleTimeout.Value)), + } + + mGrpcTimeout["idle"] = []interface{}{mIdleTimeout} + } + + if perRequestTimeout := grpcTimeout.PerRequest; perRequestTimeout != nil { + mPerRequestTimeout := map[string]interface{}{ + "unit": aws.StringValue(perRequestTimeout.Unit), + "value": int(aws.Int64Value(perRequestTimeout.Value)), + } + + mGrpcTimeout["per_request"] = []interface{}{mPerRequestTimeout} + } + + return []interface{}{mGrpcTimeout} +} + func flattenAppmeshHttpRoute(httpRoute *appmesh.HttpRoute) []interface{} { if httpRoute == nil { return []interface{}{} @@ -5912,9 +6099,39 @@ func flattenAppmeshHttpRoute(httpRoute *appmesh.HttpRoute) []interface{} { mHttpRoute["retry_policy"] = []interface{}{mHttpRetryPolicy} } + mHttpRoute["timeout"] = flattenAppmeshHttpTimeout(httpRoute.Timeout) + return []interface{}{mHttpRoute} } +func flattenAppmeshHttpTimeout(httpTimeout *appmesh.HttpTimeout) []interface{} { + if httpTimeout == nil { + return []interface{}{} + } + + mHttpTimeout := map[string]interface{}{} + + if idleTimeout := httpTimeout.Idle; idleTimeout != nil { + mIdleTimeout := map[string]interface{}{ + "unit": aws.StringValue(idleTimeout.Unit), + "value": int(aws.Int64Value(idleTimeout.Value)), + } + + mHttpTimeout["idle"] = []interface{}{mIdleTimeout} + } + + if perRequestTimeout := httpTimeout.PerRequest; perRequestTimeout != nil { + mPerRequestTimeout := map[string]interface{}{ + "unit": aws.StringValue(perRequestTimeout.Unit), + "value": int(aws.Int64Value(perRequestTimeout.Value)), + } + + mHttpTimeout["per_request"] = []interface{}{mPerRequestTimeout} + } + + return []interface{}{mHttpTimeout} +} + func flattenAppmeshTcpRoute(tcpRoute *appmesh.TcpRoute) []interface{} { if tcpRoute == nil { return []interface{}{} @@ -5943,9 +6160,30 @@ func flattenAppmeshTcpRoute(tcpRoute *appmesh.TcpRoute) []interface{} { } } + mTcpRoute["timeout"] = flattenAppmeshTcpTimeout(tcpRoute.Timeout) + return []interface{}{mTcpRoute} } +func flattenAppmeshTcpTimeout(tcpTimeout *appmesh.TcpTimeout) []interface{} { + if tcpTimeout == nil { + return []interface{}{} + } + + mTcpTimeout := map[string]interface{}{} + + if idleTimeout := tcpTimeout.Idle; idleTimeout != nil { + mIdleTimeout := map[string]interface{}{ + "unit": aws.StringValue(idleTimeout.Unit), + "value": int(aws.Int64Value(idleTimeout.Value)), + } + + mTcpTimeout["idle"] = []interface{}{mIdleTimeout} + } + + return []interface{}{mTcpTimeout} +} + func expandRoute53ResolverEndpointIpAddresses(vIpAddresses *schema.Set) []*route53resolver.IpAddressRequest { ipAddressRequests := []*route53resolver.IpAddressRequest{} diff --git a/website/docs/r/appmesh_route.html.markdown b/website/docs/r/appmesh_route.html.markdown index 19fc844b79e4..8e321381bab0 100644 --- a/website/docs/r/appmesh_route.html.markdown +++ b/website/docs/r/appmesh_route.html.markdown @@ -160,22 +160,34 @@ The `grpc_route` object supports the following: * `action` - (Required) The action to take if a match is determined. * `match` - (Required) The criteria for determining an gRPC request match. * `rety_policy` - (Optional) The retry policy. +* `timeout` - (Optional) The types of timeouts. The `http2_route` and `http_route` objects 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. +* `timeout` - (Optional) The types of timeouts. The `tcp_route` object supports the following: * `action` - (Required) The action to take if a match is determined. +* `timeout` - (Optional) The types of timeouts. The `action` object supports the following: * `weighted_target` - (Required) The targets that traffic is routed to when a request matches the route. You can specify one or more targets and their relative weights with which to distribute traffic. +The `timeout` object supports the following: + +* `idle` - (Optional) The idle timeout. An idle timeout bounds the amount of time that a connection may be idle. + +The `idle` object supports the following: + +* `unit` - (Required) The unit of time. Valid values: `ms`, `s`. +* `value` - (Required) The number of time units. Minimum value of `0`. + The `grpc_route`'s `match` object supports the following: * `metadata` - (Optional) The data to match from the gRPC request. @@ -206,6 +218,16 @@ Valid values: `client-error` (HTTP status code 409), `gateway-error` (HTTP statu * `per_retry_timeout` - (Required) The per-retry timeout. * `tcp_retry_events` - (Optional) List of TCP retry events. The only valid value is `connection-error`. +The `grpc_route`'s `timeout` object supports the following: + +* `idle` - (Optional) The idle timeout. An idle timeout bounds the amount of time that a connection may be idle. +* `per_request` - (Optional) The per request timeout. + +The `idle` and `per_request` objects support the following: + +* `unit` - (Required) The unit of time. Valid values: `ms`, `s`. +* `value` - (Required) The number of time units. Minimum value of `0`. + The `http2_route` and `http_route`'s `match` object supports the following: * `prefix` - (Required) Specifies the path with which to match requests. @@ -224,6 +246,16 @@ Valid values: `client-error` (HTTP status code 409), `gateway-error` (HTTP statu You must specify at least one value for `http_retry_events`, or at least one value for `tcp_retry_events`. +The `http2_route` and `http_route`'s `timeout` object supports the following: + +* `idle` - (Optional) The idle timeout. An idle timeout bounds the amount of time that a connection may be idle. +* `per_request` - (Optional) The per request timeout. + +The `idle` and `per_request` objects support the following: + +* `unit` - (Required) The unit of time. Valid values: `ms`, `s`. +* `value` - (Required) The number of time units. Minimum value of `0`. + The `per_retry_timeout` object supports the following: * `unit` - (Required) Retry unit. Valid values: `ms`, `s`. diff --git a/website/docs/r/appmesh_virtual_node.html.markdown b/website/docs/r/appmesh_virtual_node.html.markdown index cbd7e45354cd..c6946f2fb61c 100644 --- a/website/docs/r/appmesh_virtual_node.html.markdown +++ b/website/docs/r/appmesh_virtual_node.html.markdown @@ -231,6 +231,7 @@ The `listener` object supports the following: * `port_mapping` - (Required) The port mapping information for the listener. * `health_check` - (Optional) The health check information for the listener. +* `timeout` - (Optional) Timeouts for different protocols. * `tls` - (Optional) The Transport Layer Security (TLS) properties for the listener The `logging` object supports the following: @@ -276,6 +277,42 @@ The `health_check` object supports the following: * `path` - (Optional) The destination path for the health check request. This is only required if the specified protocol is `http` or `http2`. * `port` - (Optional) The destination port for the health check request. This port must match the port defined in the `port_mapping` for the listener. +The `timeout` object supports the following: + +* `grpc` - (Optional) Timeouts for gRPC listeners. +* `http` - (Optional) Timeouts for HTTP listeners. +* `http2` - (Optional) Timeouts for HTTP2 listeners. +* `tcp` - (Optional) Timeouts for TCP listeners. + +The `grpc` timeout object supports the following: + +* `idle` - (Optional) The idle timeout. An idle timeout bounds the amount of time that a connection may be idle. +* `per_request` - (Optional) The per request timeout. + +The `idle` and `per_request` objects support the following: + +* `unit` - (Required) The unit of time. Valid values: `ms`, `s`. +* `value` - (Required) The number of time units. Minimum value of `0`. + +The `http` and `http2` timeout objects support the following: + +* `idle` - (Optional) The idle timeout. An idle timeout bounds the amount of time that a connection may be idle. +* `per_request` - (Optional) The per request timeout. + +The `idle` and `per_request` objects support the following: + +* `unit` - (Required) The unit of time. Valid values: `ms`, `s`. +* `value` - (Required) The number of time units. Minimum value of `0`. + +The `tcp` timeout object supports the following: + +* `idle` - (Optional) The idle timeout. An idle timeout bounds the amount of time that a connection may be idle. + +The `idle` object supports the following: + +* `unit` - (Required) The unit of time. Valid values: `ms`, `s`. +* `value` - (Required) The number of time units. Minimum value of `0`. + The `tls` object supports the following: * `certificate` - (Required) The listener's TLS certificate.