Terraform-provider-aws: Disable caching on api gateway method

Created on 31 Aug 2017  路  5Comments  路  Source: hashicorp/terraform-provider-aws

Hi there!

I'm trying to disable caching for a method in API Gateway. When I add a method setting to disable caching for the method nothing seems to change in the AWS UI, the method continues to inherit stage default settings. If I set caching_enable to true for the method then the stage default settings are overriden and caching is enabled on the method.

Terraform Version

Terraform v0.10.2

Affected Resource(s)

  • aws_api_gateway_method_settings

Terraform Configuration Files

provider "aws" {
  version = "~> 0.1"

  access_key = "key"
  secret_key = "secret"
  region     = "region"
}

resource "aws_api_gateway_rest_api" "api" {
  name = "MyDemoAPI"
  description = "This is my API for demonstration purposes"
}

resource "aws_api_gateway_deployment" "dev" {
  depends_on = ["aws_api_gateway_integration.uncached_integration", "aws_api_gateway_integration.cached_integration"]
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name = "dev"
}

resource "aws_api_gateway_stage" "prod" {
  stage_name = "prod"
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  deployment_id = "${aws_api_gateway_deployment.dev.id}"

  cache_cluster_enabled = true
  cache_cluster_size = "0.5"
}

resource "aws_api_gateway_resource" "uncached_resource" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  parent_id   = "${aws_api_gateway_rest_api.api.root_resource_id}"
  path_part   = "uncached_testresource"
}

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

resource "aws_api_gateway_integration" "uncached_integration" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.uncached_resource.id}"
  http_method = "${aws_api_gateway_method.uncached_method.http_method}"
  type        = "MOCK"

  request_templates {
    "application/xml" = <<EOF
{
   "body" : $input.json('$')
}
EOF
  }
}

resource "aws_api_gateway_method_settings" "uncached_settings" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name  = "${aws_api_gateway_stage.prod.stage_name}"
  method_path = "${aws_api_gateway_resource.uncached_resource.path_part}/${aws_api_gateway_method.uncached_method.http_method}"

  settings {
    caching_enabled = false
  }
}

resource "aws_api_gateway_resource" "cached_resource" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  parent_id   = "${aws_api_gateway_rest_api.api.root_resource_id}"
  path_part   = "cached_resource"
}

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

resource "aws_api_gateway_integration" "cached_integration" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.cached_resource.id}"
  http_method = "${aws_api_gateway_method.cached_method.http_method}"
  type        = "MOCK"

  request_templates {
    "application/xml" = <<EOF
{
   "body" : $input.json('$')
}
EOF
  }
}

resource "aws_api_gateway_method_settings" "cached_settings" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name  = "${aws_api_gateway_stage.prod.stage_name}"
  method_path = "${aws_api_gateway_resource.cached_resource.path_part}/${aws_api_gateway_method.cached_method.http_method}"

  settings {
      caching_enabled = true
      cache_ttl_in_seconds = "3600"
  }
}

Debug Output

output

Expected Behavior

The uncached method should override the stage default cache settings and should not enable caching.

Actual Behavior

The uncached method inherits the stage default cache settings.

Steps to Reproduce

  1. terraform apply
    ** Aws Api Gateway UI should still show the method inheriting stage default options.
bug servicapigateway

All 5 comments

Was anybody able to take a look into this?

I have encountered this issue as well. After digging up a little bit I believe the problem occurs when the aws_api_gateway_method_settings resource only contains values that match the default value for their types (e.g., false for a boolean or 0 for an integer).

For instance, if I try to change the settings of a method by declaring:

resource "aws_api_gateway_method_settings" "foo_method_settings" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name  = "${aws_api_gateway_stage.stage.stage_name}"
  method_path = "foo/GET"
  settings {
    throttling_rate_limit = 0
  }
}

then Terraform does not perform any update patch operation as 0 is the default value (from the point of view of Terraform) for the type of field throttling_rate_limit. But, if I change throttling_rate_limit = 0 to throttling_rate_limit = 1 then the settings for method foo are correctly overridden.

This is clearly a bug as the default value for throttling_rate_limit in AWS is 10000, not 0. So, an update patch operation must be requested if throttling_rate_limit is set to 0.

I believe the problem lies in the fact that resourceAwsApiGatewayMethodSettingsUpdate is used to both to create and update the method settings:

func resourceAwsApiGatewayMethodSettings() *schema.Resource {
    return &schema.Resource{
        Create: resourceAwsApiGatewayMethodSettingsUpdate,
        Read:   resourceAwsApiGatewayMethodSettingsRead,
        Update: resourceAwsApiGatewayMethodSettingsUpdate,
        Delete: resourceAwsApiGatewayMethodSettingsDelete,

       // ...

The update function checks whether there is a change in a given setting:

func resourceAwsApiGatewayMethodSettingsUpdate(d *schema.ResourceData, meta interface{}) error {
    // ...
    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))),
        })
    }
    // ...

Although, I have not really tried, I believe d.HasChange("settings.0.throttling_rate_limit") will return false when throttling_rate_limit is set to 0 as the requested value matches the default value for the value type (float64).

I believe this can be easily solved by just using a real create method that simply passes to AWS whatever values the user has specified in the aws_api_gateway_method_settings resource. Does this sound reasonable?

Any update on this issue, or any workaround ?
Got several endpoints where caching is enable and can't disable it even if caching_enable is set to false in aws_api_gateway_method_settings


EDIT: workaround found !

Setting a aws_api_gateway_method_settings with a method_path: '*/*' and caching_enabled:false will refresh correctly others methods who have caching disabled.

Example :

aws_api_gateway_method_settings: {
    ['${PREFIX}']: {
            rest_api_id: '\${aws_api_gateway_rest_api.${PREFIX}.id}',
            stage_name: '\${aws_api_gateway_stage.${PREFIX}.stage_name}',
            method_path: '*/*',
            settings: {
                    metrics_enabled: true,
                    logging_level: 'INFO',
                    data_trace_enabled: true,
                    caching_enabled: false,
                    throttling_burst_limit: 5000,
                    throttling_rate_limit: 10000,
            }
      }
 }

Method settigns is completely broken. (Terraform v0.11.14, provider.aws v2.15.0)
These are my definitions.

resource "aws_api_gateway_method_settings" "default" {
  rest_api_id = "${aws_api_gateway_rest_api.service.id}"
  stage_name = "${aws_api_gateway_stage.v2.stage_name}"
  method_path = "*/*"

  settings {
    caching_enabled = true
    require_authorization_for_cache_control = false
    cache_ttl_in_seconds = 3600
    logging_level = "OFF"
  }

  depends_on = ["aws_api_gateway_stage.v2"]
}

resource "aws_api_gateway_method_settings" "get_source_find" {
  rest_api_id = "${aws_api_gateway_rest_api.service.id}"
  stage_name = "${aws_api_gateway_stage.v2.stage_name}"
  method_path = "${substr(aws_api_gateway_resource.source_find.path,1,-1)}/${aws_api_gateway_method.get_source_find.http_method}"

  settings {
    caching_enabled = false
  }

  depends_on = ["aws_api_gateway_stage.v2", "aws_api_gateway_method_settings.default"]
}

resource "aws_api_gateway_method_settings" "get_source_config_find" {
  rest_api_id = "${aws_api_gateway_rest_api.service.id}"
  stage_name = "${aws_api_gateway_stage.v2.stage_name}"
  method_path = "${substr(aws_api_gateway_resource.source_config_find.path,1,-1)}/${aws_api_gateway_method.get_source_config_find.http_method}"

  settings {
    caching_enabled = false
  }

  depends_on = ["aws_api_gateway_stage.v2", "aws_api_gateway_method_settings.default"]
}

And these are the logs.


 + module.source_service.aws_api_gateway_method_settings.default
      id:                                                 <computed>
      method_path:                                        "*/*"
      rest_api_id:                                        "EREASED"
      settings.#:                                         "1"
      settings.0.cache_ttl_in_seconds:                    "3600"
      settings.0.caching_enabled:                         "true"
      settings.0.logging_level:                           "OFF"
      settings.0.require_authorization_for_cache_control: "false"
      stage_name:                                         "v2"

 + module.source_service.aws_api_gateway_method_settings.get_source_config_find
      id:                                                 <computed>
      method_path:                                        "${substr(aws_api_gateway_resource.source_config_find.path,1,-1)}/${aws_api_gateway_method.get_source_config_find.http_method}"
      rest_api_id:                                        "EREASED"
      settings.#:                                         "1"
      settings.0.caching_enabled:                         "false"
      stage_name:                                         "v2"

  + module.source_service.aws_api_gateway_method_settings.get_source_find
      id:                                                 <computed>
      method_path:                                        "${substr(aws_api_gateway_resource.source_find.path,1,-1)}/${aws_api_gateway_method.get_source_find.http_method}"
      rest_api_id:                                        "EREASED"
      settings.#:                                         "1"
      settings.0.caching_enabled:                         "false"
      stage_name:                                         "v2"

It is clear that though require_authorization_for_cache_control is set to false it's not in the patch operations.

2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4: 2019/06/19 09:07:37 [DEBUG] Updating API Gateway Stage: {
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:   /: [{
  settings.#:                                         "" => "1"
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Op: "replace",
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Path: "/*/*/logging/loglevel",
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Value: "OFF"
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:     },{
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Op: "replace",
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Path: "/*/*/caching/enabled",
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Value: "true"
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:     },{
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Op: "replace",
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Path: "/*/*/caching/ttlInSeconds",
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:       Value: "3600"
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:     }],
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:   RestApiId: "EREASED",
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:   StageName: "v2"
2019-06-19T09:07:37.767+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4: }
  settings.0.cache_ttl_in_seconds:                    "" => "3600"

Disabling cache is also not in the patch operations for the other methods.

2019-06-19T09:07:38.342+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4: 2019/06/19 09:07:38 [DEBUG] Updating API Gateway Stage: {
  method_path:                "" => "source/find/GET"
2019-06-19T09:07:38.343+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:   /: [],
2019-06-19T09:07:38.343+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:   RestApiId: "EREASED",
2019-06-19T09:07:38.343+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4:   StageName: "v2"
2019-06-19T09:07:38.343+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4: }
2019-06-19T09:07:39.029+0200 [DEBUG] plugin.terraform-provider-aws_v2.15.0_x4: 2019/06/19 09:07:39 [WARN] API Gateway Method Settings for "source/find/GET" not found, removing

Using aws cli to describe the stage makes it also clear that it does not work.
Only / method setting is applied but the requireAuthorizationForCacheControl was ignored.

{
    "deploymentId": "EREASED",
    "stageName": "v2",
    "cacheClusterEnabled": true,
    "cacheClusterSize": "1.6",
    "cacheClusterStatus": "AVAILABLE",
    "methodSettings": {
        "*/*": {
            "metricsEnabled": false,
            "loggingLevel": "OFF",
            "dataTraceEnabled": false,
            "throttlingBurstLimit": 5000,
            "throttlingRateLimit": 10000.0,
            "cachingEnabled": true,
            "cacheTtlInSeconds": 3600,
            "cacheDataEncrypted": false,
            "requireAuthorizationForCacheControl": true,
            "unauthorizedCacheControlHeaderStrategy": "SUCCEED_WITH_RESPONSE_HEADER"
        }
    },
    "createdDate": 1560927844,
    "lastUpdatedDate": 1560928831
}

What you can do as a workaround if you have aws cli where you run terraform is to run aws cli commands with a local-exec provisioner either in a null resource or at the method_settings resource.

provisioner "local-exec" {
    command = "aws apigateway  update-stage --rest-api-id ${aws_api_gateway_rest_api.service.id} --stage-name ${aws_api_gateway_stage.v2.stage_name} --patch-operations op=replace,path=${aws_api_gateway_resource.source_config_find.path}/GET/caching/enabled,value=false"
  }
  provisioner "local-exec" {
    command = "aws apigateway  update-stage --rest-api-id ${aws_api_gateway_rest_api.service.id} --stage-name ${aws_api_gateway_stage.v2.stage_name} --patch-operations op=replace,path=${aws_api_gateway_resource.source_find.path}/GET/caching/enabled,value=false"
  }
  provisioner "local-exec" {
    command = "aws apigateway  update-stage --rest-api-id ${aws_api_gateway_rest_api.service.id} --stage-name ${aws_api_gateway_stage.v2.stage_name} --patch-operations op=replace,path=/*/*/caching/requireAuthorizationForCacheControl,value=false"
  }

Came across the same problem as zoltan-toth-mw.
unfortunately "Require authorization" setting is set to true by default.
the workaround I found is:

  1. set require_authorization_for_cache_control = true
  2. terraform apply
  3. set require_authorization_for_cache_control = false
  4. run terraform apply
Was this page helpful?
0 / 5 - 0 ratings