provider/aws: Add support for api_gateway_method_settings (#13542)

This commit is contained in:
Radek Simko 2017-04-12 16:13:33 +01:00 committed by GitHub
parent 414613787c
commit 4606090c32
5 changed files with 610 additions and 0 deletions

View File

@ -218,6 +218,7 @@ func Provider() terraform.ResourceProvider {
"aws_api_gateway_integration_response": resourceAwsApiGatewayIntegrationResponse(),
"aws_api_gateway_method": resourceAwsApiGatewayMethod(),
"aws_api_gateway_method_response": resourceAwsApiGatewayMethodResponse(),
"aws_api_gateway_method_settings": resourceAwsApiGatewayMethodSettings(),
"aws_api_gateway_model": resourceAwsApiGatewayModel(),
"aws_api_gateway_resource": resourceAwsApiGatewayResource(),
"aws_api_gateway_rest_api": resourceAwsApiGatewayRestApi(),

View File

@ -0,0 +1,248 @@
package aws
import (
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/apigateway"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsApiGatewayMethodSettings() *schema.Resource {
return &schema.Resource{
Create: resourceAwsApiGatewayMethodSettingsUpdate,
Read: resourceAwsApiGatewayMethodSettingsRead,
Update: resourceAwsApiGatewayMethodSettingsUpdate,
Delete: resourceAwsApiGatewayMethodSettingsDelete,
Schema: map[string]*schema.Schema{
"rest_api_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"stage_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"method_path": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"settings": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"metrics_enabled": {
Type: schema.TypeBool,
Optional: true,
},
"logging_level": {
Type: schema.TypeString,
Optional: true,
},
"data_trace_enabled": {
Type: schema.TypeBool,
Optional: true,
},
"throttling_burst_limit": {
Type: schema.TypeInt,
Optional: true,
},
"throttling_rate_limit": {
Type: schema.TypeFloat,
Optional: true,
},
"caching_enabled": {
Type: schema.TypeBool,
Optional: true,
},
"cache_ttl_in_seconds": {
Type: schema.TypeInt,
Optional: true,
},
"cache_data_encrypted": {
Type: schema.TypeBool,
Optional: true,
},
"require_authorization_for_cache_control": {
Type: schema.TypeBool,
Optional: true,
},
"unauthorized_cache_control_header_strategy": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
},
}
}
func resourceAwsApiGatewayMethodSettingsRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
log.Printf("[DEBUG] Reading API Gateway Method Settings %s", d.Id())
input := apigateway.GetStageInput{
RestApiId: aws.String(d.Get("rest_api_id").(string)),
StageName: aws.String(d.Get("stage_name").(string)),
}
stage, err := conn.GetStage(&input)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NotFoundException" {
log.Printf("[WARN] API Gateway Stage %s not found, removing method settings", d.Id())
d.SetId("")
return nil
}
return err
}
log.Printf("[DEBUG] Received API Gateway Stage: %s", stage)
methodPath := d.Get("method_path").(string)
settings, ok := stage.MethodSettings[methodPath]
if !ok {
log.Printf("[WARN] API Gateway Method Settings for %q not found, removing", methodPath)
d.SetId("")
return nil
}
d.Set("settings.0.metrics_enabled", settings.MetricsEnabled)
d.Set("settings.0.logging_level", settings.LoggingLevel)
d.Set("settings.0.data_trace_enabled", settings.DataTraceEnabled)
d.Set("settings.0.throttling_burst_limit", settings.ThrottlingBurstLimit)
d.Set("settings.0.throttling_rate_limit", settings.ThrottlingRateLimit)
d.Set("settings.0.caching_enabled", settings.CachingEnabled)
d.Set("settings.0.cache_ttl_in_seconds", settings.CacheTtlInSeconds)
d.Set("settings.0.cache_data_encrypted", settings.CacheDataEncrypted)
d.Set("settings.0.require_authorization_for_cache_control", settings.RequireAuthorizationForCacheControl)
d.Set("settings.0.unauthorized_cache_control_header_strategy", settings.UnauthorizedCacheControlHeaderStrategy)
return nil
}
func resourceAwsApiGatewayMethodSettingsUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
methodPath := d.Get("method_path").(string)
prefix := fmt.Sprintf("/%s/", methodPath)
ops := make([]*apigateway.PatchOperation, 0)
if d.HasChange("settings.0.metrics_enabled") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "metrics/enabled"),
Value: aws.String(fmt.Sprintf("%t", d.Get("settings.0.metrics_enabled").(bool))),
})
}
if d.HasChange("settings.0.logging_level") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "logging/loglevel"),
Value: aws.String(d.Get("settings.0.logging_level").(string)),
})
}
if d.HasChange("settings.0.data_trace_enabled") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "logging/dataTrace"),
Value: aws.String(fmt.Sprintf("%t", d.Get("settings.0.data_trace_enabled").(bool))),
})
}
if d.HasChange("settings.0.throttling_burst_limit") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "throttling/burstLimit"),
Value: aws.String(fmt.Sprintf("%d", d.Get("settings.0.throttling_burst_limit").(int))),
})
}
if d.HasChange("settings.0.throttling_rate_limit") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "throttling/rateLimit"),
Value: aws.String(fmt.Sprintf("%f", d.Get("settings.0.throttling_rate_limit").(float64))),
})
}
if d.HasChange("settings.0.caching_enabled") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "caching/enabled"),
Value: aws.String(fmt.Sprintf("%t", d.Get("settings.0.caching_enabled").(bool))),
})
}
if d.HasChange("settings.0.cache_ttl_in_seconds") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "caching/ttlInSeconds"),
Value: aws.String(fmt.Sprintf("%d", d.Get("settings.0.cache_ttl_in_seconds").(int))),
})
}
if d.HasChange("settings.0.cache_data_encrypted") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "caching/dataEncrypted"),
Value: aws.String(fmt.Sprintf("%d", d.Get("settings.0.cache_data_encrypted").(int))),
})
}
if d.HasChange("settings.0.require_authorization_for_cache_control") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "caching/requireAuthorizationForCacheControl"),
Value: aws.String(fmt.Sprintf("%t", d.Get("settings.0.require_authorization_for_cache_control").(bool))),
})
}
if d.HasChange("settings.0.unauthorized_cache_control_header_strategy") {
ops = append(ops, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String(prefix + "caching/unauthorizedCacheControlHeaderStrategy"),
Value: aws.String(d.Get("settings.0.unauthorized_cache_control_header_strategy").(string)),
})
}
restApiId := d.Get("rest_api_id").(string)
stageName := d.Get("stage_name").(string)
input := apigateway.UpdateStageInput{
RestApiId: aws.String(restApiId),
StageName: aws.String(stageName),
PatchOperations: ops,
}
log.Printf("[DEBUG] Updating API Gateway Stage: %s", input)
_, err := conn.UpdateStage(&input)
if err != nil {
return fmt.Errorf("Updating API Gateway Stage failed: %s", err)
}
d.SetId(restApiId + "-" + stageName + "-" + methodPath)
return resourceAwsApiGatewayMethodSettingsRead(d, meta)
}
func resourceAwsApiGatewayMethodSettingsDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
log.Printf("[DEBUG] Deleting API Gateway Method Settings: %s", d.Id())
input := apigateway.UpdateStageInput{
RestApiId: aws.String(d.Get("rest_api_id").(string)),
StageName: aws.String(d.Get("stage_name").(string)),
PatchOperations: []*apigateway.PatchOperation{
{
Op: aws.String("remove"),
Path: aws.String(fmt.Sprintf("/%s", d.Get("method_path").(string))),
},
},
}
log.Printf("[DEBUG] Updating API Gateway Stage: %s", input)
_, err := conn.UpdateStage(&input)
if err != nil {
return fmt.Errorf("Updating API Gateway Stage failed: %s", err)
}
return nil
}

View File

@ -0,0 +1,265 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/apigateway"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSAPIGatewayMethodSettings_basic(t *testing.T) {
var stage apigateway.Stage
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAPIGatewayMethodSettingsDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAPIGatewayMethodSettingsConfig(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayMethodSettingsExists("aws_api_gateway_method_settings.test", &stage),
testAccCheckAWSAPIGatewayMethodSettings_metricsEnabled(&stage, "test/GET", true),
testAccCheckAWSAPIGatewayMethodSettings_loggingLevel(&stage, "test/GET", "INFO"),
resource.TestCheckResourceAttr("aws_api_gateway_method_settings.test", "settings.#", "1"),
resource.TestCheckResourceAttr("aws_api_gateway_method_settings.test", "settings.0.metrics_enabled", "true"),
resource.TestCheckResourceAttr("aws_api_gateway_method_settings.test", "settings.0.logging_level", "INFO"),
),
},
{
Config: testAccAWSAPIGatewayMethodSettingsConfigUpdate(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayMethodSettingsExists("aws_api_gateway_method_settings.test", &stage),
testAccCheckAWSAPIGatewayMethodSettings_metricsEnabled(&stage, "test/GET", false),
testAccCheckAWSAPIGatewayMethodSettings_loggingLevel(&stage, "test/GET", "OFF"),
resource.TestCheckResourceAttr("aws_api_gateway_method_settings.test", "settings.#", "1"),
resource.TestCheckResourceAttr("aws_api_gateway_method_settings.test", "settings.0.metrics_enabled", "false"),
resource.TestCheckResourceAttr("aws_api_gateway_method_settings.test", "settings.0.logging_level", "OFF"),
),
},
},
})
}
func testAccCheckAWSAPIGatewayMethodSettings_metricsEnabled(conf *apigateway.Stage, path string, expected bool) resource.TestCheckFunc {
return func(s *terraform.State) error {
settings, ok := conf.MethodSettings[path]
if !ok {
return fmt.Errorf("Expected to find method settings for %q", path)
}
if expected && *settings.MetricsEnabled != expected {
return fmt.Errorf("Expected metrics to be enabled, got %t", *settings.MetricsEnabled)
}
if !expected && *settings.MetricsEnabled != expected {
return fmt.Errorf("Expected metrics to be disabled, got %t", *settings.MetricsEnabled)
}
return nil
}
}
func testAccCheckAWSAPIGatewayMethodSettings_loggingLevel(conf *apigateway.Stage, path string, expectedLevel string) resource.TestCheckFunc {
return func(s *terraform.State) error {
settings, ok := conf.MethodSettings[path]
if !ok {
return fmt.Errorf("Expected to find method settings for %q", path)
}
if *settings.LoggingLevel != expectedLevel {
return fmt.Errorf("Expected logging level to match %q, got %q", expectedLevel, *settings.LoggingLevel)
}
return nil
}
}
func testAccCheckAWSAPIGatewayMethodSettingsExists(n string, res *apigateway.Stage) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No API Gateway Stage ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).apigateway
req := &apigateway.GetStageInput{
StageName: aws.String(s.RootModule().Resources["aws_api_gateway_deployment.test"].Primary.Attributes["stage_name"]),
RestApiId: aws.String(s.RootModule().Resources["aws_api_gateway_rest_api.test"].Primary.ID),
}
out, err := conn.GetStage(req)
if err != nil {
return err
}
*res = *out
return nil
}
}
func testAccCheckAWSAPIGatewayMethodSettingsDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).apigateway
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_api_gateway_method_settings" {
continue
}
req := &apigateway.GetStageInput{
StageName: aws.String(s.RootModule().Resources["aws_api_gateway_deployment.test"].Primary.Attributes["stage_name"]),
RestApiId: aws.String(s.RootModule().Resources["aws_api_gateway_rest_api.test"].Primary.ID),
}
out, err := conn.GetStage(req)
if err == nil {
return fmt.Errorf("API Gateway Stage still exists: %s", out)
}
awsErr, ok := err.(awserr.Error)
if !ok {
return err
}
if awsErr.Code() != "NotFoundException" {
return err
}
return nil
}
return nil
}
func testAccAWSAPIGatewayMethodSettingsConfig(rInt int) string {
return fmt.Sprintf(`
resource "aws_api_gateway_rest_api" "test" {
name = "tf-acc-test-apig-method-%d"
}
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 = "test"
}
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.header.Content-Type" = false,
"method.request.querystring.page" = 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}"
type = "MOCK"
request_templates {
"application/xml" = <<EOF
{
"body" : $input.json('$')
}
EOF
}
}
resource "aws_api_gateway_deployment" "test" {
depends_on = ["aws_api_gateway_integration.test"]
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
stage_name = "dev"
}
resource "aws_api_gateway_method_settings" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
stage_name = "${aws_api_gateway_deployment.test.stage_name}"
method_path = "${aws_api_gateway_resource.test.path_part}/${aws_api_gateway_method.test.http_method}"
settings {
metrics_enabled = true
logging_level = "INFO"
}
}
`, rInt)
}
func testAccAWSAPIGatewayMethodSettingsConfigUpdate(rInt int) string {
return fmt.Sprintf(`
resource "aws_api_gateway_rest_api" "test" {
name = "tf-acc-test-apig-method-%d"
}
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 = "test"
}
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.header.Content-Type" = false,
"method.request.querystring.page" = 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}"
type = "MOCK"
request_templates {
"application/xml" = <<EOF
{
"body" : $input.json('$')
}
EOF
}
}
resource "aws_api_gateway_deployment" "test" {
depends_on = ["aws_api_gateway_integration.test"]
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
stage_name = "dev"
}
resource "aws_api_gateway_method_settings" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
stage_name = "${aws_api_gateway_deployment.test.stage_name}"
method_path = "${aws_api_gateway_resource.test.path_part}/${aws_api_gateway_method.test.http_method}"
settings {
metrics_enabled = false
logging_level = "OFF"
}
}
`, rInt)
}

View File

@ -0,0 +1,93 @@
---
layout: "aws"
page_title: "AWS: aws_api_gateway_method_settings"
sidebar_current: "docs-aws-resource-api-gateway-method-settings"
description: |-
Provides an API Gateway Method Settings, e.g. logging or monitoring.
---
# aws\_api\_gateway\_method\_settings
Provides an API Gateway Method Settings, e.g. logging or monitoring.
## Example Usage
```hcl
resource "aws_api_gateway_method_settings" "s" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
stage_name = "${aws_api_gateway_stage.test.stage_name}"
method_path = "${aws_api_gateway_resource.test.path_part}/${aws_api_gateway_method.test.http_method}"
settings {
metrics_enabled = true
logging_level = "INFO"
}
}
resource "aws_api_gateway_rest_api" "test" {
name = "MyDemoAPI"
description = "This is my API for demonstration purposes"
}
resource "aws_api_gateway_deployment" "test" {
depends_on = ["aws_api_gateway_integration.test"]
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
stage_name = "dev"
}
resource "aws_api_gateway_stage" "test" {
stage_name = "prod"
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
deployment_id = "${aws_api_gateway_deployment.test.id}"
}
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 = "mytestresource"
}
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"
}
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}"
type = "MOCK"
request_templates {
"application/xml" = <<EOF
{
"body" : $input.json('$')
}
EOF
}
}
```
## Argument Reference
The following arguments are supported:
* `rest_api_id` - (Required) The ID of the REST API
* `stage_name` - (Required) The name of the stage
* `method_path` - (Required) Method path defined as `{resource_path}/{http_method}` for an individual method override, or `*/*` for overriding all methods in the stage.
* `settings` - (Required) The settings block, see below.
### `settings`
* `metrics_enabled` - (Optional) Specifies whether Amazon CloudWatch metrics are enabled for this method.
* `logging_level` - (Optional) Specifies the logging level for this method, which effects the log entries pushed to Amazon CloudWatch Logs. The available levels are `OFF`, `ERROR`, and `INFO`.
* `data_trace_enabled` - (Optional) Specifies whether data trace logging is enabled for this method, which effects the log entries pushed to Amazon CloudWatch Logs.
* `throttling_burst_limit` - (Optional) Specifies the throttling burst limit.
* `throttling_rate_limit` - (Optional) Specifies the throttling rate limit.
* `caching_enabled` - (Optional) Specifies whether responses should be cached and returned for requests. A cache cluster must be enabled on the stage for responses to be cached.
* `cache_ttl_in_seconds` - (Optional) Specifies the time to live (TTL), in seconds, for cached responses. The higher the TTL, the longer the response will be cached.
* `cache_data_encrypted` - (Optional) Specifies whether the cached responses are encrypted.
* `require_authorization_for_cache_control` - (Optional) Specifies whether authorization is required for a cache invalidation request.
* `unauthorized_cache_control_header_strategy` - (Optional) Specifies how to handle unauthorized requests for cache invalidation. The available values are `FAIL_WITH_403`, `SUCCEED_WITH_RESPONSE_HEADER`, `SUCCEED_WITHOUT_RESPONSE_HEADER`.

View File

@ -176,6 +176,9 @@
<li<%= sidebar_current("docs-aws-resource-api-gateway-method-response") %>>
<a href="/docs/providers/aws/r/api_gateway_method_response.html">aws_api_gateway_method_response</a>
</li>
<li<%= sidebar_current("docs-aws-resource-api-gateway-method-settings") %>>
<a href="/docs/providers/aws/r/api_gateway_method_settings.html">aws_api_gateway_method_settings</a>
</li>
<li<%= sidebar_current("docs-aws-resource-api-gateway-model") %>>
<a href="/docs/providers/aws/r/api_gateway_model.html">aws_api_gateway_model</a>
</li>