Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for specifying cache key parameters in API Gateway. #893

Merged
merged 4 commits into from
Jun 27, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions aws/resource_aws_api_gateway_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ func resourceAwsApiGatewayIntegration() *schema.Resource {
ForceNew: true,
ValidateFunc: validateApiGatewayIntegrationPassthroughBehavior,
},

"cache_key_parameters": {
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Optional: true,
},
},
}
}
Expand Down Expand Up @@ -150,6 +157,11 @@ func resourceAwsApiGatewayIntegrationCreate(d *schema.ResourceData, meta interfa
contentHandling = aws.String(val.(string))
}

var cacheKeyParameters []*string
if v, ok := d.GetOk("cache_key_parameters"); ok {
cacheKeyParameters = expandStringList(v.(*schema.Set).List())
}

_, err := conn.PutIntegration(&apigateway.PutIntegrationInput{
HttpMethod: aws.String(d.Get("http_method").(string)),
ResourceId: aws.String(d.Get("resource_id").(string)),
Expand All @@ -160,8 +172,8 @@ func resourceAwsApiGatewayIntegrationCreate(d *schema.ResourceData, meta interfa
RequestParameters: aws.StringMap(parameters),
RequestTemplates: aws.StringMap(templates),
Credentials: credentials,
CacheNamespace: nil,
CacheKeyParameters: nil,
CacheNamespace: aws.String(d.Get("resource_id").(string)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason the cache namespace should always be resource ID?
I had a peek 👀 into the official API docs and couldn't find any suggestions around that: https://docs.aws.amazon.com/apigateway/api-reference/link-relation/integration-put/#cacheNamespace

If there isn't a reason I think we should let the user specify their own namespace.

Also I'm not sure what kind of data it contains and how these are structured, so it's hard to tell (for me at least) whether resource_id is the best namespace key - e.g. does it automatically assign the cache distribution to a given API ID so that we don't need to put API ID to the namespace? Same questions about other fields. If it's not clear from the docs it would be worth asking the AWS support - I'm happy to ask for you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think we should leave this as nil in case the user didn't specify any caching.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I observed that when caching was manually enabled the namespace set by AWS matched the resource id. But, as you well say it might not be a requirement. I will conduct a test using a custom namespace. If it works, users should indeed be able to specify it.

In the meanwhile, if you can please ask AWS support that would be great. Hopefully we can then have a clear understanding of the usage (and the potential restrictions) of a cache namespace.

Setting the default to nil sounds good to me. I will do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just updated the pull request with your feedback. I did some testing and using a user-defined cache namespace works too. So, I added a field named cache_namespace.

CacheKeyParameters: cacheKeyParameters,
PassthroughBehavior: passthroughBehavior,
ContentHandling: contentHandling,
})
Expand Down Expand Up @@ -216,6 +228,8 @@ func resourceAwsApiGatewayIntegrationRead(d *schema.ResourceData, meta interface
d.Set("content_handling", integration.ContentHandling)
}

d.Set("cache_key_parameters", flattenStringList(integration.CacheKeyParameters))

return nil
}

Expand Down Expand Up @@ -303,6 +317,31 @@ func resourceAwsApiGatewayIntegrationUpdate(d *schema.ResourceData, meta interfa
}
}

if d.HasChange("cache_key_parameters") {
o, n := d.GetChange("cache_key_parameters")

os := o.(*schema.Set)
ns := n.(*schema.Set)

removalList := os.Difference(ns)
for _, v := range removalList.List() {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("remove"),
Path: aws.String(fmt.Sprintf("/cacheKeyParameters/%s", v.(string))),
Value: aws.String(""),
})
}

additionList := ns.Difference(os)
for _, v := range additionList.List() {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("add"),
Path: aws.String(fmt.Sprintf("/cacheKeyParameters/%s", v.(string))),
Value: aws.String(""),
})
}
}

params := &apigateway.UpdateIntegrationInput{
HttpMethod: aws.String(d.Get("http_method").(string)),
ResourceId: aws.String(d.Get("resource_id").(string)),
Expand Down
74 changes: 74 additions & 0 deletions aws/resource_aws_api_gateway_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,28 @@ func TestAccAWSAPIGatewayIntegration_basic(t *testing.T) {
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/xml", "#set($inputRoot = $input.path('$'))\n{ }"),
),
},

{
Config: testAccAWSAPIGatewayIntegrationConfigCacheKeyParameters,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of expanding this _basic test would you mind creating a separate one? That way we can also run tests much faster as we generally run whole tests in parallel, we cannot do that with test steps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean adding a new function named func TestAccAWSAPIGatewayIntegration_cache_key_parameters(t *testing.T) (or similar) to the same file resource_aws_api_gateway_integration_test.go?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestAccAWSAPIGatewayIntegration_cache_key_parameters - that's pretty much what I mean. There is no need for a new file.

Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayIntegrationExists("aws_api_gateway_integration.test", &conf),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "type", "HTTP"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "integration_http_method", "GET"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "uri", "https://www.google.de"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "passthrough_behavior", "WHEN_NO_MATCH"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "content_handling", "CONVERT_TO_TEXT"),
resource.TestCheckNoResourceAttr("aws_api_gateway_integration.test", "credentials"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.%", "3"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.header.X-Authorization", "'static'"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.header.X-Foo", "'Bar'"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.path.param", "method.request.path.param"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "cache_key_parameters.#", "1"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "cache_key_parameters.550492954", "method.request.path.param"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.%", "2"),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/json", ""),
resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/xml", "#set($inputRoot = $input.path('$'))\n{ }"),
),
},
},
})
}
Expand Down Expand Up @@ -279,3 +301,55 @@ resource "aws_api_gateway_integration" "test" {
content_handling = "CONVERT_TO_TEXT"
}
`

const testAccAWSAPIGatewayIntegrationConfigCacheKeyParameters = `
resource "aws_api_gateway_rest_api" "test" {
name = "test"
}

resource "aws_api_gateway_resource" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
parent_id = "${aws_api_gateway_rest_api.test.root_resource_id}"
path_part = "{param}"
}

resource "aws_api_gateway_method" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "GET"
authorization = "NONE"

request_models = {
"application/json" = "Error"
}

request_parameters = {
"method.request.path.param" = true
}
}

resource "aws_api_gateway_integration" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "${aws_api_gateway_method.test.http_method}"

request_templates = {
"application/json" = ""
"application/xml" = "#set($inputRoot = $input.path('$'))\n{ }"
}

request_parameters = {
"integration.request.header.X-Authorization" = "'static'"
"integration.request.header.X-Foo" = "'Bar'"
"integration.request.path.param" = "method.request.path.param"
}

cache_key_parameters = ["method.request.path.param"]

type = "HTTP"
uri = "https://www.google.de"
integration_http_method = "GET"
passthrough_behavior = "WHEN_NO_MATCH"
content_handling = "CONVERT_TO_TEXT"
}
`