Skip to content

Commit

Permalink
New module to request quota increase for an AWS resource (#34)
Browse files Browse the repository at this point in the history
* Add new module to request quota increase for a resource

* Add nat_gateway

* Add docs related to terraform destroy and smaller requests

* Add test case to check if the quota_code is correct

* Add reference to the readme on how to find the codes

* Add usage example

* Using OutputStruct instead OutputMapOfObjects

Co-authored-by: Yevgeniy Brikman <[email protected]>
  • Loading branch information
Marina and brikis98 authored Jan 12, 2021
1 parent 9fecff9 commit 155f414
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 0 deletions.
11 changes: 11 additions & 0 deletions examples/request-quota-increase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Request AWS Quota Increase

This folder shows examples of how to use the [request-quota-increase module](/modules/request-quota-increase) to request a bigger quota for an AWS resource.


## How do you run these examples?

1. Install [Terraform](https://www.terraform.io/).
1. `terraform init`.
1. `terraform apply`.

21 changes: 21 additions & 0 deletions examples/request-quota-increase/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
terraform {
# This module is now only being tested with Terraform 0.13.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 0.13.x code.
required_version = ">= 0.12.26"
}

provider "aws" {
region = var.aws_region
}

module "quota-increase" {
source = "../../modules/request-quota-increase"

resources_to_increase = {
# In this example, to avoid opening a new request every time we run an automated test, we are setting the quotas
# to their default values. In the real world, you'd want to set these quotes to higher values.
nat_gateway = 5
nacl_rules = 20
}
}
3 changes: 3 additions & 0 deletions examples/request-quota-increase/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "new_quotas" {
value = module.quota-increase.new_quotas
}
5 changes: 5 additions & 0 deletions examples/request-quota-increase/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
variable "aws_region" {
description = "The AWS region to run this code in"
type = string
default = "us-east-1"
}
116 changes: 116 additions & 0 deletions modules/request-quota-increase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Request AWS Quota Increase

This module can be used to request a quota increase for an AWS Resource.

## Features

- Request a quota increase for Network ACL Rules and NAT Gateway.

## Learn

### Core Concepts

- [AWS Service Quotas Documentation](https://docs.aws.amazon.com/servicequotas/?id=docs_gateway)


### Example code

See the [request-quota-increase example](/examples/request-quota-increase) for working sample code.



## Usage

Use the module in your Terraform code, replacing `<VERSION>` with the latest version from the [releases
page](https://github.com/gruntwork-io/package-terraform-utilities/releases):

```hcl
module "path" {
source = "git::[email protected]:gruntwork-io/package-terraform-utilities.git//modules/quota-increase?ref=<VERSION>"
request_quota_increase = {
nat_gateway = 40,
nacl_rules = 25
}
}
```

The argument to pass is:

* `request_quota_increase`: A map with the desired resource and the new quota. The current supported resources are `nat_gateway` and `nacl_rules`. Feel free to contribute to this module to add support for more `quota_code` and `service_code` options in [main.tf](main.tf)!


When you run `apply`, the `new_quotas` output variable will confirm to you that a quota request has been made!

```hcl
new_quotas = {
"nat_gateway" = {
"adjustable" = true
"arn" = "arn:aws:servicequotas:us-east-1:<account-id>:vpc/L-FE5A380F"
"default_value" = 5
"id" = "vpc/L-FE5A380F"
"quota_code" = "L-FE5A380F"
"quota_name" = "NAT gateways per Availability Zone"
"request_id" = "<request_id>"
"request_status" = "PENDING"
"service_code" = "vpc"
"service_name" = "Amazon Virtual Private Cloud (Amazon VPC)"
"value" = 30
}
}
```

## Manage

You can see a full history of quota request changes using the [AWS
Console](https://console.aws.amazon.com/servicequotas/home#!/requests) or the AWS CLI:


```
aws service-quotas list-requested-service-quota-change-history --region <REGION>
```

### Finding out the Service Code and Quota Code

When you need to add a new resource, you can check the available services with

```
aws service-quotas list-services --region <REGION> --output table
```

And use the `ServiceCode` from the output to get the code for the resources

```
aws service-quotas list-service-quotas --service-code <SERVICE_CODE>
```


### Request a new quota smaller than the current one

If the new value that you request is smaller than the current one, _nothing_ will happen. The
`terraform apply` output will contain the current quota. For example, if the NAT Gateway current
quota is 30 and you ask for a new quota of 25, this is the output:

```hcl
new_quotas = {
"nat_gateway" = {
"adjustable" = true
"arn" = "arn:aws:servicequotas:us-east-1:<account-id>:vpc/L-FE5A380F"
"default_value" = 5
"id" = "vpc/L-FE5A380F"
"quota_code" = "L-FE5A380F"
"quota_name" = "NAT gateways per Availability Zone"
"service_code" = "vpc"
"service_name" = "Amazon Virtual Private Cloud (Amazon VPC)"
"value" = 30 <------ Returned the current quota, not the requested one.
}
}
```


### What happens when you run `destroy`


When you run `terraform destroy` on this module, it does not affect your current quotas or your
existing quota requests. In other words, you don't have to worry about quotas being reset to old
values; once they have been increased, they stay that way!
26 changes: 26 additions & 0 deletions modules/request-quota-increase/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
terraform {
required_version = ">= 0.12.26"
}

resource "aws_servicequotas_service_quota" "increase_quotas" {
for_each = var.resources_to_increase

quota_code = local.codes[each.key].quota_code
service_code = local.codes[each.key].service_code
value = each.value
}

locals {
# PRs to add more of these mappings are very welcome. For more information
# on how to find the Service Code and Quota Code, see the README.md!
codes = {
nacl_rules = {
quota_code = "L-2AEEBF1A"
service_code = "vpc"
},
nat_gateway = {
quota_code = "L-FE5A380F"
service_code = "vpc"
}
}
}
3 changes: 3 additions & 0 deletions modules/request-quota-increase/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "new_quotas" {
value = aws_servicequotas_service_quota.increase_quotas
}
10 changes: 10 additions & 0 deletions modules/request-quota-increase/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
variable "resources_to_increase" {
description = "A map where the key is the resource and the value is the desired quota. The only resources supported at the moment are 'nacl_rules' and 'nat_gateway'. You can also use the `aws_servicequotas_service_quota` resource directly, there are instructions on how to find the Service Code and Quota Code on the README!"
type = map(number)

# Example:
# {
# nacl_rules = 39,
# nat_gateway = 20,
# }
}
45 changes: 45 additions & 0 deletions test/request_quota_increase_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package test

import (
"github.com/gruntwork-io/terratest/modules/aws"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
"testing"
)

type (
QuotaAndServiceName struct {
QuotaName string `json:"quota_name"`
ServiceName string `json:"service_name"`
}
QuotaIncreaseOutput struct {
NatGateway QuotaAndServiceName `json:"nat_gateway"`
NaclRules QuotaAndServiceName `json:"nacl_rules"`
}
)

func TestRequestQuotaIncrease(t *testing.T) {
t.Parallel()

awsRegion := aws.GetRandomRegion(t, nil, nil)

terraformOptions := &terraform.Options{
TerraformDir: "../examples/request-quota-increase",
Vars: map[string]interface{}{
"aws_region": awsRegion,
},
}

defer terraform.Destroy(t, terraformOptions)

terraform.InitAndApply(t, terraformOptions)

output := QuotaIncreaseOutput{}
terraform.OutputStruct(t, terraformOptions, "new_quotas", &output)

assert.Equal(t, output.NatGateway.QuotaName, "NAT gateways per Availability Zone")
assert.Equal(t, output.NatGateway.ServiceName, "Amazon Virtual Private Cloud (Amazon VPC)")

assert.Equal(t, output.NaclRules.QuotaName, "Rules per network ACL")
assert.Equal(t, output.NaclRules.ServiceName, "Amazon Virtual Private Cloud (Amazon VPC)")
}

0 comments on commit 155f414

Please sign in to comment.