provider/aws: Add support for api_gateway_account (#6321)
This commit is contained in:
parent
0194cfda0a
commit
e3ade6a784
|
@ -114,6 +114,7 @@ func Provider() terraform.ResourceProvider {
|
|||
"aws_ami": resourceAwsAmi(),
|
||||
"aws_ami_copy": resourceAwsAmiCopy(),
|
||||
"aws_ami_from_instance": resourceAwsAmiFromInstance(),
|
||||
"aws_api_gateway_account": resourceAwsApiGatewayAccount(),
|
||||
"aws_api_gateway_api_key": resourceAwsApiGatewayApiKey(),
|
||||
"aws_api_gateway_authorizer": resourceAwsApiGatewayAuthorizer(),
|
||||
"aws_api_gateway_deployment": resourceAwsApiGatewayDeployment(),
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"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/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsApiGatewayAccount() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsApiGatewayAccountUpdate,
|
||||
Read: resourceAwsApiGatewayAccountRead,
|
||||
Update: resourceAwsApiGatewayAccountUpdate,
|
||||
Delete: resourceAwsApiGatewayAccountDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"cloudwatch_role_arn": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
"throttle_settings": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
MaxItems: 1,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"burst_limit": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"rate_limit": &schema.Schema{
|
||||
Type: schema.TypeFloat,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsApiGatewayAccountRead(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).apigateway
|
||||
|
||||
log.Printf("[INFO] Reading API Gateway Account %s", d.Id())
|
||||
account, err := conn.GetAccount(&apigateway.GetAccountInput{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Received API Gateway Account: %s", account)
|
||||
|
||||
if _, ok := d.GetOk("cloudwatch_role_arn"); ok {
|
||||
// CloudwatchRoleArn cannot be empty nor made empty via API
|
||||
// This resource can however be useful w/out defining cloudwatch_role_arn
|
||||
// (e.g. for referencing throttle_settings)
|
||||
d.Set("cloudwatch_role_arn", account.CloudwatchRoleArn)
|
||||
}
|
||||
d.Set("throttle_settings", flattenApiGatewayThrottleSettings(account.ThrottleSettings))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsApiGatewayAccountUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).apigateway
|
||||
|
||||
input := apigateway.UpdateAccountInput{}
|
||||
operations := make([]*apigateway.PatchOperation, 0)
|
||||
|
||||
if d.HasChange("cloudwatch_role_arn") {
|
||||
arn := d.Get("cloudwatch_role_arn").(string)
|
||||
if len(arn) > 0 {
|
||||
// Unfortunately AWS API doesn't allow empty ARNs,
|
||||
// even though that's default settings for new AWS accounts
|
||||
// BadRequestException: The role ARN is not well formed
|
||||
operations = append(operations, &apigateway.PatchOperation{
|
||||
Op: aws.String("replace"),
|
||||
Path: aws.String("/cloudwatchRoleArn"),
|
||||
Value: aws.String(arn),
|
||||
})
|
||||
}
|
||||
}
|
||||
input.PatchOperations = operations
|
||||
|
||||
log.Printf("[INFO] Updating API Gateway Account: %s", input)
|
||||
|
||||
// Retry due to eventual consistency of IAM
|
||||
expectedErrMsg := "The role ARN does not have required permissions set to API Gateway"
|
||||
var out *apigateway.Account
|
||||
var err error
|
||||
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
||||
out, err = conn.UpdateAccount(&input)
|
||||
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "BadRequestException" &&
|
||||
awsErr.Message() == expectedErrMsg {
|
||||
log.Printf("[DEBUG] Retrying API Gateway Account update: %s", awsErr)
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Updating API Gateway Account failed: %s", err)
|
||||
}
|
||||
log.Printf("[DEBUG] API Gateway Account updated: %s", out)
|
||||
|
||||
d.SetId("api-gateway-account")
|
||||
return resourceAwsApiGatewayAccountRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsApiGatewayAccountDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
// There is no API for "deleting" account or resetting it to "default" settings
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/apigateway"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAWSAPIGatewayAccount_basic(t *testing.T) {
|
||||
var conf apigateway.Account
|
||||
|
||||
expectedRoleArn_first := regexp.MustCompile("[0-9]+")
|
||||
expectedRoleArn_second := regexp.MustCompile("[0-9]+")
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSAPIGatewayAccountDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSAPIGatewayAccountConfig_updated,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSAPIGatewayAccountExists("aws_api_gateway_account.test", &conf),
|
||||
testAccCheckAWSAPIGatewayAccountCloudwatchRoleArn(&conf, expectedRoleArn_first),
|
||||
resource.TestMatchResourceAttr("aws_api_gateway_account.test", "cloudwatch_role_arn", expectedRoleArn_first),
|
||||
),
|
||||
},
|
||||
resource.TestStep{
|
||||
Config: testAccAWSAPIGatewayAccountConfig_updated2,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSAPIGatewayAccountExists("aws_api_gateway_account.test", &conf),
|
||||
testAccCheckAWSAPIGatewayAccountCloudwatchRoleArn(&conf, expectedRoleArn_second),
|
||||
resource.TestMatchResourceAttr("aws_api_gateway_account.test", "cloudwatch_role_arn", expectedRoleArn_second),
|
||||
),
|
||||
},
|
||||
resource.TestStep{
|
||||
Config: testAccAWSAPIGatewayAccountConfig_empty,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSAPIGatewayAccountExists("aws_api_gateway_account.test", &conf),
|
||||
testAccCheckAWSAPIGatewayAccountCloudwatchRoleArn(&conf, expectedRoleArn_second),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAWSAPIGatewayAccountCloudwatchRoleArn(conf *apigateway.Account, expectedArn *regexp.Regexp) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
if expectedArn == nil && conf.CloudwatchRoleArn == nil {
|
||||
return nil
|
||||
}
|
||||
if expectedArn == nil && conf.CloudwatchRoleArn != nil {
|
||||
return fmt.Errorf("Expected empty CloudwatchRoleArn, given: %q", *conf.CloudwatchRoleArn)
|
||||
}
|
||||
if expectedArn != nil && conf.CloudwatchRoleArn == nil {
|
||||
return fmt.Errorf("Empty CloudwatchRoleArn, expected: %q", expectedArn)
|
||||
}
|
||||
if !expectedArn.MatchString(*conf.CloudwatchRoleArn) {
|
||||
return fmt.Errorf("CloudwatchRoleArn didn't match. Expected: %q, Given: %q", expectedArn, *conf.CloudwatchRoleArn)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAWSAPIGatewayAccountExists(n string, res *apigateway.Account) 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 Account ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AWSClient).apigateway
|
||||
|
||||
req := &apigateway.GetAccountInput{}
|
||||
describe, err := conn.GetAccount(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if describe == nil {
|
||||
return fmt.Errorf("Got nil account ?!")
|
||||
}
|
||||
|
||||
*res = *describe
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAWSAPIGatewayAccountDestroy(s *terraform.State) error {
|
||||
// Intentionally noop
|
||||
// as there is no API method for deleting or resetting account settings
|
||||
return nil
|
||||
}
|
||||
|
||||
const testAccAWSAPIGatewayAccountConfig_empty = `
|
||||
resource "aws_api_gateway_account" "test" {
|
||||
}
|
||||
`
|
||||
|
||||
const testAccAWSAPIGatewayAccountConfig_updated = `
|
||||
resource "aws_api_gateway_account" "test" {
|
||||
cloudwatch_role_arn = "${aws_iam_role.cloudwatch.arn}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "cloudwatch" {
|
||||
name = "api_gateway_cloudwatch_global"
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": "apigateway.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "cloudwatch" {
|
||||
name = "default"
|
||||
role = "${aws_iam_role.cloudwatch.id}"
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:DescribeLogGroups",
|
||||
"logs:DescribeLogStreams",
|
||||
"logs:PutLogEvents",
|
||||
"logs:GetLogEvents",
|
||||
"logs:FilterLogEvents"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
`
|
||||
const testAccAWSAPIGatewayAccountConfig_updated2 = `
|
||||
resource "aws_api_gateway_account" "test" {
|
||||
cloudwatch_role_arn = "${aws_iam_role.second.arn}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "second" {
|
||||
name = "api_gateway_cloudwatch_global_modified"
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": "apigateway.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "cloudwatch" {
|
||||
name = "default"
|
||||
role = "${aws_iam_role.second.id}"
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:DescribeLogGroups",
|
||||
"logs:DescribeLogStreams",
|
||||
"logs:PutLogEvents",
|
||||
"logs:GetLogEvents",
|
||||
"logs:FilterLogEvents"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
`
|
|
@ -1097,3 +1097,22 @@ func sortInterfaceSlice(in []interface{}) []interface{} {
|
|||
|
||||
return b
|
||||
}
|
||||
|
||||
func flattenApiGatewayThrottleSettings(settings *apigateway.ThrottleSettings) []map[string]interface{} {
|
||||
result := make([]map[string]interface{}, 0, 1)
|
||||
|
||||
if settings != nil {
|
||||
r := make(map[string]interface{})
|
||||
if settings.BurstLimit != nil {
|
||||
r["burst_limit"] = *settings.BurstLimit
|
||||
}
|
||||
|
||||
if settings.RateLimit != nil {
|
||||
r["rate_limit"] = *settings.RateLimit
|
||||
}
|
||||
|
||||
result = append(result, r)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/apigateway"
|
||||
"github.com/aws/aws-sdk-go/service/autoscaling"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/elasticache"
|
||||
|
@ -902,3 +903,42 @@ func TestFlattenSecurityGroups(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlattenApiGatewayThrottleSettings(t *testing.T) {
|
||||
expectedBurstLimit := int64(140)
|
||||
expectedRateLimit := 120.0
|
||||
|
||||
ts := &apigateway.ThrottleSettings{
|
||||
BurstLimit: aws.Int64(expectedBurstLimit),
|
||||
RateLimit: aws.Float64(expectedRateLimit),
|
||||
}
|
||||
result := flattenApiGatewayThrottleSettings(ts)
|
||||
|
||||
if len(result) != 1 {
|
||||
t.Fatalf("Expected map to have exactly 1 element, got %d", len(result))
|
||||
}
|
||||
|
||||
burstLimit, ok := result[0]["burst_limit"]
|
||||
if !ok {
|
||||
t.Fatal("Expected 'burst_limit' key in the map")
|
||||
}
|
||||
burstLimitInt, ok := burstLimit.(int64)
|
||||
if !ok {
|
||||
t.Fatal("Expected 'burst_limit' to be int")
|
||||
}
|
||||
if burstLimitInt != expectedBurstLimit {
|
||||
t.Fatalf("Expected 'burst_limit' to equal %d, got %d", expectedBurstLimit, burstLimitInt)
|
||||
}
|
||||
|
||||
rateLimit, ok := result[0]["rate_limit"]
|
||||
if !ok {
|
||||
t.Fatal("Expected 'rate_limit' key in the map")
|
||||
}
|
||||
rateLimitFloat, ok := rateLimit.(float64)
|
||||
if !ok {
|
||||
t.Fatal("Expected 'rate_limit' to be float64")
|
||||
}
|
||||
if rateLimitFloat != expectedRateLimit {
|
||||
t.Fatalf("Expected 'rate_limit' to equal %f, got %f", expectedRateLimit, rateLimitFloat)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_api_gateway_account"
|
||||
sidebar_current: "docs-aws-resource-api-gateway-account"
|
||||
description: |-
|
||||
Provides a settings of an API Gateway Account.
|
||||
---
|
||||
|
||||
# aws\_api\_gateway\_account
|
||||
|
||||
Provides a settings of an API Gateway Account. Settings is applied region-wide per `provider` block.
|
||||
|
||||
-> **Note:** As there is no API method for deleting account settings or resetting it to defaults, destroying this resource will keep your account settings intact
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
resource "aws_api_gateway_account" "demo" {
|
||||
cloudwatch_role_arn = "${aws_iam_role.cloudwatch.arn}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "cloudwatch" {
|
||||
name = "api_gateway_cloudwatch_global"
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": "apigateway.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "cloudwatch" {
|
||||
name = "default"
|
||||
role = "${aws_iam_role.cloudwatch.id}"
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:DescribeLogGroups",
|
||||
"logs:DescribeLogStreams",
|
||||
"logs:PutLogEvents",
|
||||
"logs:GetLogEvents",
|
||||
"logs:FilterLogEvents"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following argument is supported:
|
||||
|
||||
* `cloudwatch_role_arn` - (Optional) The ARN of an IAM role for CloudWatch (to allow logging & monitoring).
|
||||
See more [in AWS Docs](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-stage-settings.html#how-to-stage-settings-console).
|
||||
Logging & monitoring can be enabled/disabled and otherwise tuned on the API Gateway Stage level.
|
||||
|
||||
## Attribute Reference
|
||||
|
||||
The following attribute is exported:
|
||||
|
||||
* `throttle_settings` - Account-Level throttle settings. See exported fields below.
|
||||
|
||||
`throttle_settings` block exports the following:
|
||||
|
||||
* `burst_limit` - The absolute maximum number of times API Gateway allows the API to be called per second (RPS).
|
||||
* `rate_limit` - The number of times API Gateway allows the API to be called per second on average (RPS).
|
|
@ -13,6 +13,9 @@
|
|||
<li<%= sidebar_current(/^docs-aws-resource-api-gateway/) %>>
|
||||
<a href="#">API Gateway Resources</a>
|
||||
<ul class="nav nav-visible">
|
||||
<li<%= sidebar_current("docs-aws-resource-api-gateway-account") %>>
|
||||
<a href="/docs/providers/aws/r/api_gateway_account.html">aws_api_gateway_account</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-aws-resource-api-gateway-api-key") %>>
|
||||
<a href="/docs/providers/aws/r/api_gateway_api_key.html">aws_api_gateway_api_key</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue