Skip to content

Commit ff67ef0

Browse files
Merge pull request #16867 from ewbankkit/b-aws_appmesh_route-empty-grpc_route
r/aws_appmesh_route: Allow empty 'match' for 'grpc_route'
2 parents 44eb67e + f8ba388 commit ff67ef0

4 files changed

Lines changed: 142 additions & 60 deletions

File tree

aws/resource_aws_appmesh_route.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ func resourceAwsAppmeshRoute() *schema.Resource {
103103

104104
"match": {
105105
Type: schema.TypeList,
106-
Required: true,
107-
MinItems: 1,
106+
Optional: true,
107+
MinItems: 0,
108108
MaxItems: 1,
109109
Elem: &schema.Resource{
110110
Schema: map[string]*schema.Schema{
@@ -196,8 +196,9 @@ func resourceAwsAppmeshRoute() *schema.Resource {
196196
},
197197

198198
"service_name": {
199-
Type: schema.TypeString,
200-
Optional: true,
199+
Type: schema.TypeString,
200+
Optional: true,
201+
RequiredWith: []string{"spec.0.grpc_route.0.match.0.method_name"},
201202
},
202203
},
203204
},

aws/resource_aws_appmesh_route_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,58 @@ func testAccAwsAppmeshRoute_grpcRouteTimeout(t *testing.T) {
368368
})
369369
}
370370

371+
func testAccAwsAppmeshRoute_grpcRouteEmptyMatch(t *testing.T) {
372+
var r appmesh.RouteData
373+
resourceName := "aws_appmesh_route.test"
374+
meshName := acctest.RandomWithPrefix("tf-acc-test")
375+
vrName := acctest.RandomWithPrefix("tf-acc-test")
376+
vn1Name := acctest.RandomWithPrefix("tf-acc-test")
377+
vn2Name := acctest.RandomWithPrefix("tf-acc-test")
378+
rName := acctest.RandomWithPrefix("tf-acc-test")
379+
380+
resource.Test(t, resource.TestCase{
381+
PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(appmesh.EndpointsID, t) },
382+
Providers: testAccProviders,
383+
CheckDestroy: testAccCheckAppmeshRouteDestroy,
384+
Steps: []resource.TestStep{
385+
{
386+
Config: testAccAwsAppmeshRouteConfig_grpcRouteWithEmptyMatch(meshName, vrName, vn1Name, vn2Name, rName),
387+
Check: resource.ComposeTestCheckFunc(
388+
testAccCheckAppmeshRouteExists(resourceName, &r),
389+
resource.TestCheckResourceAttr(resourceName, "name", rName),
390+
resource.TestCheckResourceAttr(resourceName, "mesh_name", meshName),
391+
testAccCheckResourceAttrAccountID(resourceName, "mesh_owner"),
392+
resource.TestCheckResourceAttr(resourceName, "virtual_router_name", vrName),
393+
resource.TestCheckResourceAttr(resourceName, "spec.#", "1"),
394+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.#", "1"),
395+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.action.#", "1"),
396+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.action.0.weighted_target.#", "1"),
397+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.#", "1"),
398+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.metadata.#", "0"),
399+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.method_name", ""),
400+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.match.0.service_name", ""),
401+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.retry_policy.#", "0"),
402+
resource.TestCheckResourceAttr(resourceName, "spec.0.grpc_route.0.timeout.#", "0"),
403+
resource.TestCheckResourceAttr(resourceName, "spec.0.http2_route.#", "0"),
404+
resource.TestCheckResourceAttr(resourceName, "spec.0.http_route.#", "0"),
405+
resource.TestCheckResourceAttr(resourceName, "spec.0.tcp_route.#", "0"),
406+
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
407+
resource.TestCheckResourceAttrSet(resourceName, "created_date"),
408+
resource.TestCheckResourceAttrSet(resourceName, "last_updated_date"),
409+
testAccCheckResourceAttrAccountID(resourceName, "resource_owner"),
410+
testAccCheckResourceAttrRegionalARN(resourceName, "arn", "appmesh", fmt.Sprintf("mesh/%s/virtualRouter/%s/route/%s", meshName, vrName, rName)),
411+
),
412+
},
413+
{
414+
ResourceName: resourceName,
415+
ImportStateIdFunc: testAccAwsAppmeshRouteImportStateIdFunc(resourceName),
416+
ImportState: true,
417+
ImportStateVerify: true,
418+
},
419+
},
420+
})
421+
}
422+
371423
func testAccAwsAppmeshRoute_http2Route(t *testing.T) {
372424
var r appmesh.RouteData
373425
resourceName := "aws_appmesh_route.test"
@@ -1645,6 +1697,29 @@ resource "aws_appmesh_route" "test" {
16451697
`, rName))
16461698
}
16471699

1700+
func testAccAwsAppmeshRouteConfig_grpcRouteWithEmptyMatch(meshName, vrName, vn1Name, vn2Name, rName string) string {
1701+
return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "grpc", vn1Name, vn2Name), fmt.Sprintf(`
1702+
resource "aws_appmesh_route" "test" {
1703+
name = %[1]q
1704+
mesh_name = aws_appmesh_mesh.test.id
1705+
virtual_router_name = aws_appmesh_virtual_router.test.name
1706+
1707+
spec {
1708+
grpc_route {
1709+
match {}
1710+
1711+
action {
1712+
weighted_target {
1713+
virtual_node = aws_appmesh_virtual_node.foo.name
1714+
weight = 100
1715+
}
1716+
}
1717+
}
1718+
}
1719+
}
1720+
`, rName))
1721+
}
1722+
16481723
func testAccAwsAppmeshRouteConfig_http2Route(meshName, vrName, vn1Name, vn2Name, rName string) string {
16491724
return composeConfig(testAccAppmeshRouteConfigBase(meshName, vrName, "http2", vn1Name, vn2Name), fmt.Sprintf(`
16501725
resource "aws_appmesh_route" "test" {

aws/resource_aws_appmesh_test.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,19 @@ func TestAccAWSAppmesh_serial(t *testing.T) {
2020
"tags": testAccAwsAppmeshMesh_tags,
2121
},
2222
"Route": {
23-
"grpcRoute": testAccAwsAppmeshRoute_grpcRoute,
24-
"grpcRouteTimeout": testAccAwsAppmeshRoute_grpcRouteTimeout,
25-
"http2Route": testAccAwsAppmeshRoute_http2Route,
26-
"http2RouteTimeout": testAccAwsAppmeshRoute_http2RouteTimeout,
27-
"httpHeader": testAccAwsAppmeshRoute_httpHeader,
28-
"httpRetryPolicy": testAccAwsAppmeshRoute_httpRetryPolicy,
29-
"httpRoute": testAccAwsAppmeshRoute_httpRoute,
30-
"httpRouteTimeout": testAccAwsAppmeshRoute_httpRouteTimeout,
31-
"routePriority": testAccAwsAppmeshRoute_routePriority,
32-
"tcpRoute": testAccAwsAppmeshRoute_tcpRoute,
33-
"tcpRouteTimeout": testAccAwsAppmeshRoute_tcpRouteTimeout,
34-
"tags": testAccAwsAppmeshRoute_tags,
23+
"grpcRoute": testAccAwsAppmeshRoute_grpcRoute,
24+
"grpcRouteEmptyMatch": testAccAwsAppmeshRoute_grpcRouteEmptyMatch,
25+
"grpcRouteTimeout": testAccAwsAppmeshRoute_grpcRouteTimeout,
26+
"http2Route": testAccAwsAppmeshRoute_http2Route,
27+
"http2RouteTimeout": testAccAwsAppmeshRoute_http2RouteTimeout,
28+
"httpHeader": testAccAwsAppmeshRoute_httpHeader,
29+
"httpRetryPolicy": testAccAwsAppmeshRoute_httpRetryPolicy,
30+
"httpRoute": testAccAwsAppmeshRoute_httpRoute,
31+
"httpRouteTimeout": testAccAwsAppmeshRoute_httpRouteTimeout,
32+
"routePriority": testAccAwsAppmeshRoute_routePriority,
33+
"tcpRoute": testAccAwsAppmeshRoute_tcpRoute,
34+
"tcpRouteTimeout": testAccAwsAppmeshRoute_tcpRouteTimeout,
35+
"tags": testAccAwsAppmeshRoute_tags,
3536
},
3637
"VirtualGateway": {
3738
"basic": testAccAwsAppmeshVirtualGateway_basic,

aws/structure.go

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5512,69 +5512,74 @@ func expandAppmeshGrpcRoute(vGrpcRoute []interface{}) *appmesh.GrpcRoute {
55125512
}
55135513
}
55145514

5515-
if vGrpcRouteMatch, ok := mGrpcRoute["match"].([]interface{}); ok && len(vGrpcRouteMatch) > 0 && vGrpcRouteMatch[0] != nil {
5515+
if vGrpcRouteMatch, ok := mGrpcRoute["match"].([]interface{}); ok {
55165516
grpcRouteMatch := &appmesh.GrpcRouteMatch{}
55175517

5518-
mGrpcRouteMatch := vGrpcRouteMatch[0].(map[string]interface{})
5518+
// Empty match is allowed.
5519+
// https://github.com/hashicorp/terraform-provider-aws/issues/16816.
55195520

5520-
if vMethodName, ok := mGrpcRouteMatch["method_name"].(string); ok && vMethodName != "" {
5521-
grpcRouteMatch.MethodName = aws.String(vMethodName)
5522-
}
5523-
if vServiceName, ok := mGrpcRouteMatch["service_name"].(string); ok && vServiceName != "" {
5524-
grpcRouteMatch.ServiceName = aws.String(vServiceName)
5525-
}
5526-
5527-
if vGrpcRouteMetadatas, ok := mGrpcRouteMatch["metadata"].(*schema.Set); ok && vGrpcRouteMetadatas.Len() > 0 {
5528-
grpcRouteMetadatas := []*appmesh.GrpcRouteMetadata{}
5529-
5530-
for _, vGrpcRouteMetadata := range vGrpcRouteMetadatas.List() {
5531-
grpcRouteMetadata := &appmesh.GrpcRouteMetadata{}
5521+
if len(vGrpcRouteMatch) > 0 && vGrpcRouteMatch[0] != nil {
5522+
mGrpcRouteMatch := vGrpcRouteMatch[0].(map[string]interface{})
55325523

5533-
mGrpcRouteMetadata := vGrpcRouteMetadata.(map[string]interface{})
5524+
if vMethodName, ok := mGrpcRouteMatch["method_name"].(string); ok && vMethodName != "" {
5525+
grpcRouteMatch.MethodName = aws.String(vMethodName)
5526+
}
5527+
if vServiceName, ok := mGrpcRouteMatch["service_name"].(string); ok && vServiceName != "" {
5528+
grpcRouteMatch.ServiceName = aws.String(vServiceName)
5529+
}
55345530

5535-
if vInvert, ok := mGrpcRouteMetadata["invert"].(bool); ok {
5536-
grpcRouteMetadata.Invert = aws.Bool(vInvert)
5537-
}
5538-
if vName, ok := mGrpcRouteMetadata["name"].(string); ok && vName != "" {
5539-
grpcRouteMetadata.Name = aws.String(vName)
5540-
}
5531+
if vGrpcRouteMetadatas, ok := mGrpcRouteMatch["metadata"].(*schema.Set); ok && vGrpcRouteMetadatas.Len() > 0 {
5532+
grpcRouteMetadatas := []*appmesh.GrpcRouteMetadata{}
55415533

5542-
if vMatch, ok := mGrpcRouteMetadata["match"].([]interface{}); ok && len(vMatch) > 0 && vMatch[0] != nil {
5543-
grpcRouteMetadata.Match = &appmesh.GrpcRouteMetadataMatchMethod{}
5534+
for _, vGrpcRouteMetadata := range vGrpcRouteMetadatas.List() {
5535+
grpcRouteMetadata := &appmesh.GrpcRouteMetadata{}
55445536

5545-
mMatch := vMatch[0].(map[string]interface{})
5537+
mGrpcRouteMetadata := vGrpcRouteMetadata.(map[string]interface{})
55465538

5547-
if vExact, ok := mMatch["exact"].(string); ok && vExact != "" {
5548-
grpcRouteMetadata.Match.Exact = aws.String(vExact)
5539+
if vInvert, ok := mGrpcRouteMetadata["invert"].(bool); ok {
5540+
grpcRouteMetadata.Invert = aws.Bool(vInvert)
55495541
}
5550-
if vPrefix, ok := mMatch["prefix"].(string); ok && vPrefix != "" {
5551-
grpcRouteMetadata.Match.Prefix = aws.String(vPrefix)
5552-
}
5553-
if vRegex, ok := mMatch["regex"].(string); ok && vRegex != "" {
5554-
grpcRouteMetadata.Match.Regex = aws.String(vRegex)
5555-
}
5556-
if vSuffix, ok := mMatch["suffix"].(string); ok && vSuffix != "" {
5557-
grpcRouteMetadata.Match.Suffix = aws.String(vSuffix)
5542+
if vName, ok := mGrpcRouteMetadata["name"].(string); ok && vName != "" {
5543+
grpcRouteMetadata.Name = aws.String(vName)
55585544
}
55595545

5560-
if vRange, ok := mMatch["range"].([]interface{}); ok && len(vRange) > 0 && vRange[0] != nil {
5561-
grpcRouteMetadata.Match.Range = &appmesh.MatchRange{}
5546+
if vMatch, ok := mGrpcRouteMetadata["match"].([]interface{}); ok && len(vMatch) > 0 && vMatch[0] != nil {
5547+
grpcRouteMetadata.Match = &appmesh.GrpcRouteMetadataMatchMethod{}
55625548

5563-
mRange := vRange[0].(map[string]interface{})
5549+
mMatch := vMatch[0].(map[string]interface{})
55645550

5565-
if vEnd, ok := mRange["end"].(int); ok && vEnd > 0 {
5566-
grpcRouteMetadata.Match.Range.End = aws.Int64(int64(vEnd))
5551+
if vExact, ok := mMatch["exact"].(string); ok && vExact != "" {
5552+
grpcRouteMetadata.Match.Exact = aws.String(vExact)
55675553
}
5568-
if vStart, ok := mRange["start"].(int); ok && vStart > 0 {
5569-
grpcRouteMetadata.Match.Range.Start = aws.Int64(int64(vStart))
5554+
if vPrefix, ok := mMatch["prefix"].(string); ok && vPrefix != "" {
5555+
grpcRouteMetadata.Match.Prefix = aws.String(vPrefix)
5556+
}
5557+
if vRegex, ok := mMatch["regex"].(string); ok && vRegex != "" {
5558+
grpcRouteMetadata.Match.Regex = aws.String(vRegex)
5559+
}
5560+
if vSuffix, ok := mMatch["suffix"].(string); ok && vSuffix != "" {
5561+
grpcRouteMetadata.Match.Suffix = aws.String(vSuffix)
5562+
}
5563+
5564+
if vRange, ok := mMatch["range"].([]interface{}); ok && len(vRange) > 0 && vRange[0] != nil {
5565+
grpcRouteMetadata.Match.Range = &appmesh.MatchRange{}
5566+
5567+
mRange := vRange[0].(map[string]interface{})
5568+
5569+
if vEnd, ok := mRange["end"].(int); ok && vEnd > 0 {
5570+
grpcRouteMetadata.Match.Range.End = aws.Int64(int64(vEnd))
5571+
}
5572+
if vStart, ok := mRange["start"].(int); ok && vStart > 0 {
5573+
grpcRouteMetadata.Match.Range.Start = aws.Int64(int64(vStart))
5574+
}
55705575
}
55715576
}
5577+
5578+
grpcRouteMetadatas = append(grpcRouteMetadatas, grpcRouteMetadata)
55725579
}
55735580

5574-
grpcRouteMetadatas = append(grpcRouteMetadatas, grpcRouteMetadata)
5581+
grpcRouteMatch.Metadata = grpcRouteMetadatas
55755582
}
5576-
5577-
grpcRouteMatch.Metadata = grpcRouteMetadatas
55785583
}
55795584

55805585
grpcRoute.Match = grpcRouteMatch

0 commit comments

Comments
 (0)