Skip to content

Commit

Permalink
r/aws_appmesh_route: Support gRPC and HTTP/2 services.
Browse files Browse the repository at this point in the history
  • Loading branch information
ewbankkit committed Feb 29, 2020
1 parent df7825f commit 6a00f48
Show file tree
Hide file tree
Showing 5 changed files with 1,243 additions and 215 deletions.
313 changes: 284 additions & 29 deletions aws/resource_aws_appmesh_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ func resourceAwsAppmeshRoute() *schema.Resource {
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"http_route": {
"grpc_route": {
Type: schema.TypeList,
Optional: true,
MinItems: 0,
MaxItems: 1,
ConflictsWith: []string{"spec.0.tcp_route"},
ConflictsWith: []string{"spec.0.http2_route", "spec.0.http_route", "spec.0.tcp_route"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"action": {
Expand Down Expand Up @@ -103,7 +103,7 @@ func resourceAwsAppmeshRoute() *schema.Resource {
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"header": {
"metadata": {
Type: schema.TypeSet,
Optional: true,
MinItems: 0,
Expand Down Expand Up @@ -177,38 +177,18 @@ func resourceAwsAppmeshRoute() *schema.Resource {
},
},
},
Set: appmeshHttpRouteHeaderHash,
Set: appmeshGrpcRouteMetadataHash,
},

"method": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
appmesh.HttpMethodConnect,
appmesh.HttpMethodDelete,
appmesh.HttpMethodGet,
appmesh.HttpMethodHead,
appmesh.HttpMethodOptions,
appmesh.HttpMethodPatch,
appmesh.HttpMethodPost,
appmesh.HttpMethodPut,
appmesh.HttpMethodTrace,
}, false),
},

"prefix": {
"method_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^/`), "must start with /"),
Optional: true,
ValidateFunc: validation.StringLenBetween(0, 50),
},

"scheme": {
"service_name": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
appmesh.HttpSchemeHttp,
appmesh.HttpSchemeHttps,
}, false),
},
},
},
Expand All @@ -221,6 +201,14 @@ func resourceAwsAppmeshRoute() *schema.Resource {
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"grpc_retry_events": {
Type: schema.TypeSet,
Optional: true,
MinItems: 0,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"http_retry_events": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -272,6 +260,18 @@ func resourceAwsAppmeshRoute() *schema.Resource {
},
},

"http2_route": func() *schema.Schema {
schema := appmeshRouteHttpRouteSchema()
schema.ConflictsWith = []string{"spec.0.grpc_route", "spec.0.http_route", "spec.0.tcp_route"}
return schema
}(),

"http_route": func() *schema.Schema {
schema := appmeshRouteHttpRouteSchema()
schema.ConflictsWith = []string{"spec.0.grpc_route", "spec.0.http2_route", "spec.0.tcp_route"}
return schema
}(),

"priority": {
Type: schema.TypeInt,
Optional: true,
Expand All @@ -283,7 +283,7 @@ func resourceAwsAppmeshRoute() *schema.Resource {
Optional: true,
MinItems: 0,
MaxItems: 1,
ConflictsWith: []string{"spec.0.http_route"},
ConflictsWith: []string{"spec.0.grpc_route", "spec.0.http2_route", "spec.0.http_route"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"action": {
Expand Down Expand Up @@ -345,6 +345,225 @@ func resourceAwsAppmeshRoute() *schema.Resource {
}
}

// appmeshRouteHttpRouteSchema returns the schema for `http2_route` and `http_route` attributes.
func appmeshRouteHttpRouteSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
MinItems: 0,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"action": {
Type: schema.TypeList,
Required: true,
MinItems: 1,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"weighted_target": {
Type: schema.TypeSet,
Required: true,
MinItems: 1,
MaxItems: 10,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"virtual_node": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringLenBetween(1, 255),
},

"weight": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(0, 100),
},
},
},
Set: appmeshWeightedTargetHash,
},
},
},
},

"match": {
Type: schema.TypeList,
Required: true,
MinItems: 1,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"header": {
Type: schema.TypeSet,
Optional: true,
MinItems: 0,
MaxItems: 10,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"invert": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},

"match": {
Type: schema.TypeList,
Optional: true,
MinItems: 0,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"exact": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(1, 255),
},

"prefix": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(1, 255),
},

"range": {
Type: schema.TypeList,
Optional: true,
MinItems: 0,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"end": {
Type: schema.TypeInt,
Required: true,
},

"start": {
Type: schema.TypeInt,
Required: true,
},
},
},
},

"regex": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(1, 255),
},

"suffix": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(1, 255),
},
},
},
},

"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringLenBetween(1, 50),
},
},
},
Set: appmeshHttpRouteHeaderHash,
},

"method": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
appmesh.HttpMethodConnect,
appmesh.HttpMethodDelete,
appmesh.HttpMethodGet,
appmesh.HttpMethodHead,
appmesh.HttpMethodOptions,
appmesh.HttpMethodPatch,
appmesh.HttpMethodPost,
appmesh.HttpMethodPut,
appmesh.HttpMethodTrace,
}, false),
},

"prefix": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^/`), "must start with /"),
},

"scheme": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
appmesh.HttpSchemeHttp,
appmesh.HttpSchemeHttps,
}, false),
},
},
},
},

"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,
Required: true,
},

"per_retry_timeout": {
Type: schema.TypeList,
Required: true,
MinItems: 1,
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,
},
},
},
},
},
},
}
}

func resourceAwsAppmeshRouteCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).appmeshconn

Expand Down Expand Up @@ -494,6 +713,42 @@ func resourceAwsAppmeshRouteImport(d *schema.ResourceData, meta interface{}) ([]
return []*schema.ResourceData{d}, nil
}

func appmeshGrpcRouteMetadataHash(vGrpcRouteMetadata interface{}) int {
var buf bytes.Buffer
mGrpcRouteMetadata := vGrpcRouteMetadata.(map[string]interface{})
if v, ok := mGrpcRouteMetadata["invert"].(bool); ok {
buf.WriteString(fmt.Sprintf("%t-", v))
}
if vMatch, ok := mGrpcRouteMetadata["match"].([]interface{}); ok && len(vMatch) > 0 && vMatch[0] != nil {
mMatch := vMatch[0].(map[string]interface{})
if v, ok := mMatch["exact"].(string); ok {
buf.WriteString(fmt.Sprintf("%s-", v))
}
if v, ok := mMatch["prefix"].(string); ok {
buf.WriteString(fmt.Sprintf("%s-", v))
}
if vRange, ok := mMatch["range"].([]interface{}); ok && len(vRange) > 0 && vRange[0] != nil {
mRange := vRange[0].(map[string]interface{})
if v, ok := mRange["end"].(int); ok {
buf.WriteString(fmt.Sprintf("%d-", v))
}
if v, ok := mRange["start"].(int); ok {
buf.WriteString(fmt.Sprintf("%d-", v))
}
}
if v, ok := mMatch["regex"].(string); ok {
buf.WriteString(fmt.Sprintf("%s-", v))
}
if v, ok := mMatch["suffix"].(string); ok {
buf.WriteString(fmt.Sprintf("%s-", v))
}
}
if v, ok := mGrpcRouteMetadata["name"].(string); ok {
buf.WriteString(fmt.Sprintf("%s-", v))
}
return hashcode.String(buf.String())
}

func appmeshHttpRouteHeaderHash(vHttpRouteHeader interface{}) int {
var buf bytes.Buffer
mHttpRouteHeader := vHttpRouteHeader.(map[string]interface{})
Expand Down
Loading

0 comments on commit 6a00f48

Please sign in to comment.