Merge #8353: New resources for custom domains on AWS API Gateway

This commit is contained in:
Martin Atkins 2016-08-22 15:44:52 -07:00
commit 38289ddbd5
9 changed files with 792 additions and 0 deletions

View File

@ -1,5 +1,8 @@
## 0.7.2 (Unreleased) ## 0.7.2 (Unreleased)
FEATURES:
* **New Resources:** `aws_api_gateway_domain_name` and `aws_api_gateway_base_path_mapping`, for using custom domains in AWS API Gateway [GH-8353]
BUG FIXES: BUG FIXES:
* core: fix crash case when malformed JSON given [GH-8295] * core: fix crash case when malformed JSON given [GH-8295]
* core: when asking for input, spaces are allowed [GH-8394] * core: when asking for input, spaces are allowed [GH-8394]

View File

@ -164,7 +164,9 @@ func Provider() terraform.ResourceProvider {
"aws_api_gateway_account": resourceAwsApiGatewayAccount(), "aws_api_gateway_account": resourceAwsApiGatewayAccount(),
"aws_api_gateway_api_key": resourceAwsApiGatewayApiKey(), "aws_api_gateway_api_key": resourceAwsApiGatewayApiKey(),
"aws_api_gateway_authorizer": resourceAwsApiGatewayAuthorizer(), "aws_api_gateway_authorizer": resourceAwsApiGatewayAuthorizer(),
"aws_api_gateway_base_path_mapping": resourceAwsApiGatewayBasePathMapping(),
"aws_api_gateway_deployment": resourceAwsApiGatewayDeployment(), "aws_api_gateway_deployment": resourceAwsApiGatewayDeployment(),
"aws_api_gateway_domain_name": resourceAwsApiGatewayDomainName(),
"aws_api_gateway_integration": resourceAwsApiGatewayIntegration(), "aws_api_gateway_integration": resourceAwsApiGatewayIntegration(),
"aws_api_gateway_integration_response": resourceAwsApiGatewayIntegrationResponse(), "aws_api_gateway_integration_response": resourceAwsApiGatewayIntegrationResponse(),
"aws_api_gateway_method": resourceAwsApiGatewayMethod(), "aws_api_gateway_method": resourceAwsApiGatewayMethod(),

View File

@ -0,0 +1,128 @@
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 resourceAwsApiGatewayBasePathMapping() *schema.Resource {
return &schema.Resource{
Create: resourceAwsApiGatewayBasePathMappingCreate,
Read: resourceAwsApiGatewayBasePathMappingRead,
Delete: resourceAwsApiGatewayBasePathMappingDelete,
Schema: map[string]*schema.Schema{
"api_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"base_path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"stage_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"domain_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}
func resourceAwsApiGatewayBasePathMappingCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
err := resource.Retry(30*time.Second, func() *resource.RetryError {
_, err := conn.CreateBasePathMapping(&apigateway.CreateBasePathMappingInput{
RestApiId: aws.String(d.Get("api_id").(string)),
DomainName: aws.String(d.Get("domain_name").(string)),
BasePath: aws.String(d.Get("base_path").(string)),
Stage: aws.String(d.Get("stage_name").(string)),
})
if err != nil {
if err, ok := err.(awserr.Error); ok && err.Code() != "BadRequestException" {
return resource.NonRetryableError(err)
}
return resource.RetryableError(
fmt.Errorf("Error creating Gateway base path mapping: %s", err),
)
}
return nil
})
if err != nil {
return fmt.Errorf("Error creating Gateway base path mapping: %s", err)
}
id := fmt.Sprintf("%s/%s", d.Get("domain_name").(string), d.Get("base_path").(string))
d.SetId(id)
return resourceAwsApiGatewayBasePathMappingRead(d, meta)
}
func resourceAwsApiGatewayBasePathMappingRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
domainName := d.Get("domain_name").(string)
basePath := d.Get("base_path").(string)
if domainName == "" {
return nil
}
mapping, err := conn.GetBasePathMapping(&apigateway.GetBasePathMappingInput{
DomainName: aws.String(domainName),
BasePath: aws.String(basePath),
})
if err != nil {
if err, ok := err.(awserr.Error); ok && err.Code() == "NotFoundException" {
log.Printf("[WARN] API gateway base path mapping %s has vanished\n", d.Id())
d.SetId("")
return nil
}
return fmt.Errorf("Error reading Gateway base path mapping: %s", err)
}
d.Set("base_path", *mapping.BasePath)
d.Set("api_id", *mapping.RestApiId)
d.Set("stage_name", *mapping.Stage)
return nil
}
func resourceAwsApiGatewayBasePathMappingDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
_, err := conn.DeleteBasePathMapping(&apigateway.DeleteBasePathMappingInput{
DomainName: aws.String(d.Get("domain_name").(string)),
BasePath: aws.String(d.Get("base_path").(string)),
})
if err != nil {
if err, ok := err.(awserr.Error); ok && err.Code() == "NotFoundException" {
return nil
}
return err
}
return nil
}

View File

@ -0,0 +1,138 @@
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/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSAPIGatewayBasePath_basic(t *testing.T) {
var conf apigateway.BasePathMapping
// Our test cert is for a wildcard on this domain
name := fmt.Sprintf("%s.tf-acc.invalid", resource.UniqueId())
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAPIGatewayBasePathDestroy(name),
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSAPIGatewayBasePathConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayBasePathExists("aws_api_gateway_base_path_mapping.test", name, &conf),
),
},
},
})
}
func testAccCheckAWSAPIGatewayBasePathExists(n string, name string, res *apigateway.BasePathMapping) 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 ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).apigateway
req := &apigateway.GetBasePathMappingInput{
DomainName: aws.String(name),
BasePath: aws.String("tf-acc"),
}
describe, err := conn.GetBasePathMapping(req)
if err != nil {
return err
}
if *describe.BasePath != "tf-acc" {
return fmt.Errorf("base path mapping not found")
}
*res = *describe
return nil
}
}
func testAccCheckAWSAPIGatewayBasePathDestroy(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).apigateway
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_api_gateway_rest_api" {
continue
}
req := &apigateway.GetBasePathMappingsInput{
DomainName: aws.String(name),
}
_, err := conn.GetBasePathMappings(req)
if err != nil {
if err, ok := err.(awserr.Error); ok && err.Code() == "NotFoundException" {
return nil
}
return err
}
return fmt.Errorf("expected error reading deleted base path, but got success")
}
return nil
}
}
func testAccAWSAPIGatewayBasePathConfig(name string) string {
return fmt.Sprintf(`
resource "aws_api_gateway_rest_api" "test" {
name = "tf-acc-apigateway-base-path-mapping"
description = "Terraform Acceptance Tests"
}
# API gateway won't let us deploy an empty API
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 = "tf-acc"
}
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"
}
resource "aws_api_gateway_deployment" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
stage_name = "test"
depends_on = ["aws_api_gateway_integration.test"]
}
resource "aws_api_gateway_base_path_mapping" "test" {
api_id = "${aws_api_gateway_rest_api.test.id}"
base_path = "tf-acc"
stage_name = "${aws_api_gateway_deployment.test.stage_name}"
domain_name = "${aws_api_gateway_domain_name.test.domain_name}"
}
resource "aws_api_gateway_domain_name" "test" {
domain_name = "%s"
certificate_name = "tf-apigateway-base-path-mapping-test"
certificate_body = "%s"
certificate_chain = "%s"
certificate_private_key = "%s"
}
`, name, testAccAWSAPIGatewayCertBody, testAccAWSAPIGatewayCertChain, testAccAWSAPIGatewayCertPrivateKey)
}

View File

@ -0,0 +1,182 @@
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 resourceAwsApiGatewayDomainName() *schema.Resource {
return &schema.Resource{
Create: resourceAwsApiGatewayDomainNameCreate,
Read: resourceAwsApiGatewayDomainNameRead,
Update: resourceAwsApiGatewayDomainNameUpdate,
Delete: resourceAwsApiGatewayDomainNameDelete,
Schema: map[string]*schema.Schema{
"certificate_body": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"certificate_chain": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"certificate_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"certificate_private_key": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"domain_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"cloudfront_domain_name": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"cloudfront_zone_id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceAwsApiGatewayDomainNameCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
log.Printf("[DEBUG] Creating API Gateway Domain Name")
domainName, err := conn.CreateDomainName(&apigateway.CreateDomainNameInput{
CertificateBody: aws.String(d.Get("certificate_body").(string)),
CertificateChain: aws.String(d.Get("certificate_chain").(string)),
CertificateName: aws.String(d.Get("certificate_name").(string)),
CertificatePrivateKey: aws.String(d.Get("certificate_private_key").(string)),
DomainName: aws.String(d.Get("domain_name").(string)),
})
if err != nil {
return fmt.Errorf("Error creating API Gateway Domain Name: %s", err)
}
d.SetId(*domainName.DomainName)
d.Set("cloudfront_domain_name", *domainName.DistributionDomainName)
d.Set("cloudfront_zone_id", cloudFrontRoute53ZoneID)
return resourceAwsApiGatewayDomainNameRead(d, meta)
}
func resourceAwsApiGatewayDomainNameRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
log.Printf("[DEBUG] Reading API Gateway Domain Name %s", d.Id())
domainName, err := conn.GetDomainName(&apigateway.GetDomainNameInput{
DomainName: aws.String(d.Id()),
})
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NotFoundException" {
log.Printf("[WARN] API gateway domain name %s has vanished\n", d.Id())
d.SetId("")
return nil
}
return err
}
d.Set("certificate_name", domainName.CertificateName)
d.Set("certificate_upload_date", domainName.CertificateUploadDate)
d.Set("cloudfront_domain_name", domainName.DistributionDomainName)
d.Set("domain_name", domainName.DomainName)
return nil
}
func resourceAwsApiGatewayDomainNameUpdateOperations(d *schema.ResourceData) []*apigateway.PatchOperation {
operations := make([]*apigateway.PatchOperation, 0)
if d.HasChange("certificate_body") {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String("/certificate_body"),
Value: aws.String(d.Get("certificate_body").(string)),
})
}
if d.HasChange("certificate_chain") {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String("/certificate_chain"),
Value: aws.String(d.Get("certificate_chain").(string)),
})
}
if d.HasChange("certificate_name") {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String("/certificate_name"),
Value: aws.String(d.Get("certificate_name").(string)),
})
}
if d.HasChange("certificate_private_key") {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("replace"),
Path: aws.String("/certificate_private_key"),
Value: aws.String(d.Get("certificate_private_key").(string)),
})
}
return operations
}
func resourceAwsApiGatewayDomainNameUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
log.Printf("[DEBUG] Updating API Gateway Domain Name %s", d.Id())
_, err := conn.UpdateDomainName(&apigateway.UpdateDomainNameInput{
DomainName: aws.String(d.Id()),
PatchOperations: resourceAwsApiGatewayDomainNameUpdateOperations(d),
})
if err != nil {
return err
}
return resourceAwsApiGatewayDomainNameRead(d, meta)
}
func resourceAwsApiGatewayDomainNameDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigateway
log.Printf("[DEBUG] Deleting API Gateway Domain Name: %s", d.Id())
return resource.Retry(5*time.Minute, func() *resource.RetryError {
_, err := conn.DeleteDomainName(&apigateway.DeleteDomainNameInput{
DomainName: aws.String(d.Id()),
})
if err == nil {
return nil
}
if apigatewayErr, ok := err.(awserr.Error); ok && apigatewayErr.Code() == "NotFoundException" {
return nil
}
return resource.NonRetryableError(err)
})
}

View File

@ -0,0 +1,211 @@
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/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSAPIGatewayDomainName_basic(t *testing.T) {
var conf apigateway.DomainName
// Our test cert is for a wildcard on this domain
name := fmt.Sprintf("%s.tf-acc.invalid", resource.UniqueId())
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAPIGatewayDomainNameDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSAPIGatewayDomainNameConfigCreate(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayDomainNameExists("aws_api_gateway_domain_name.test", &conf),
resource.TestCheckResourceAttr(
"aws_api_gateway_domain_name.test", "certificate_body", testAccAWSAPIGatewayCertBody,
),
resource.TestCheckResourceAttr(
"aws_api_gateway_domain_name.test", "certificate_chain", testAccAWSAPIGatewayCertChain,
),
resource.TestCheckResourceAttr(
"aws_api_gateway_domain_name.test", "certificate_name", "tf-acc-apigateway-domain-name",
),
resource.TestCheckResourceAttr(
"aws_api_gateway_domain_name.test", "certificate_private_key", testAccAWSAPIGatewayCertPrivateKey,
),
resource.TestCheckResourceAttr(
"aws_api_gateway_domain_name.test", "domain_name", name,
),
),
},
},
})
}
func testAccCheckAWSAPIGatewayDomainNameExists(n string, res *apigateway.DomainName) 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 DomainName ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).apigateway
req := &apigateway.GetDomainNameInput{
DomainName: aws.String(rs.Primary.ID),
}
describe, err := conn.GetDomainName(req)
if err != nil {
return err
}
if *describe.DomainName != rs.Primary.ID {
return fmt.Errorf("APIGateway DomainName not found")
}
*res = *describe
return nil
}
}
func testAccCheckAWSAPIGatewayDomainNameDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).apigateway
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_api_gateway_api_key" {
continue
}
describe, err := conn.GetDomainNames(&apigateway.GetDomainNamesInput{})
if err == nil {
if len(describe.Items) != 0 &&
*describe.Items[0].DomainName == rs.Primary.ID {
return fmt.Errorf("API Gateway DomainName still exists")
}
}
aws2err, ok := err.(awserr.Error)
if !ok {
return err
}
if aws2err.Code() != "NotFoundException" {
return err
}
return nil
}
return nil
}
// Expires on August 20, 2026
const testAccAWSAPIGatewayCertBody = `-----BEGIN CERTIFICATE-----
MIIEfjCCA2agAwIBAgIRAPHiUbRWC/Ff/reiyzqh3wAwDQYJKoZIhvcNAQELBQAw
gcsxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNUGlyYXRlIEhh
cmJvcjEZMBcGA1UECRMQNTg3OSBDb3R0b24gTGluazETMBEGA1UEERMKOTU1NTkt
MTIyNzEVMBMGA1UEChMMRXhhbXBsZSwgSW5jMSgwJgYDVQQLEx9EZXBhcnRtZW50
IG9mIFRlcnJhZm9ybSBUZXN0aW5nMRowGAYDVQQDExF0Zi1hY2MtY2EuaW52YWxp
ZDEKMAgGA1UEBRMBMjAeFw0xNjA4MjIxNjQ1NTZaFw0yNjA4MjAxNjQ1NTZaMIHK
MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVBpcmF0ZSBIYXJi
b3IxGTAXBgNVBAkTEDU4NzkgQ290dG9uIExpbmsxEzARBgNVBBETCjk1NTU5LTEy
MjcxFTATBgNVBAoTDEV4YW1wbGUsIEluYzEoMCYGA1UECxMfRGVwYXJ0bWVudCBv
ZiBUZXJyYWZvcm0gVGVzdGluZzEZMBcGA1UEAxMQKi50Zi1hY2MuaW52YWxpZDEK
MAgGA1UEBRMBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/xTPoz
3tnvkLjthqsMKwWVtE1yi210UnseBYkc2w6iQUXMCsXkw2PZXW6QIW7o1GNjnrE5
9jkeEJ2ABEYyor+ooaNZmjJ0dvY1tFerMhsOkQudDBz+eaR13UQvMFc42nFWrS5/
XCInm4HjWblEfw2b/wbGwTPzIN3+zWdt2XTsSzIRUYgjXy/93aLIVhWaYDsP45RM
C48qhJKSsYOVH/PSkgw4AfohDXzn2iltTUBFdGZqBufMW4sPp8G8DIOvt01NsXB2
QLLVgcMJVegx9xxg50+cf6ILck5Ap/SzkCN7XYk8zWC36/QIkiQ6bMMy0nJtgE0B
jwmwnFF+zF/A4oMCAwEAAaNcMFowDgYDVR0PAQH/BAQDAgWgMBkGA1UdJQQSMBAG
CCsGAQUFBwMBBgRVHSUAMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU/hWQ+UUh
7EiLd0fCsgy1jvSgxkswDQYJKoZIhvcNAQELBQADggEBABnTdSEOqj2+7FTeiSR9
iPGQ3swhrmk59j8XUszrlm6MvZX9AeV9gLcE9J0PfFaAcZM0pR+XZBmyZLoBxUgU
8Y17yWwAxZo13EwgzTOmebDxm4W+Og4vBxsKS3x/L8D8BKdzBcmVJvggJqTs5Qau
ePetAQcD/Tfbq7vY9fNQJ4XQTlF5sN625miijTQcNg/s/H2Fj3FENR3UaFiQDtLQ
eatV0KGF/ik8XFHPbFm7XUZfUcDxvoaljglJfXyVttU956j892ZakvAHzhylFRyy
/wJnKV7K3zQVCEV0n/dJpXhf7w9PuWHrCp+HZJLMPMtm1IPblVxPNwHhGBG40I+Z
FSg=
-----END CERTIFICATE-----
`
// Expires on August 20, 2026
const testAccAWSAPIGatewayCertChain = `-----BEGIN CERTIFICATE-----
MIIEoDCCA4igAwIBAgIQRR1EBw7bN+mMYtXrrvzLdzANBgkqhkiG9w0BAQsFADCB
yzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1QaXJhdGUgSGFy
Ym9yMRkwFwYDVQQJExA1ODc5IENvdHRvbiBMaW5rMRMwEQYDVQQREwo5NTU1OS0x
MjI3MRUwEwYDVQQKEwxFeGFtcGxlLCBJbmMxKDAmBgNVBAsTH0RlcGFydG1lbnQg
b2YgVGVycmFmb3JtIFRlc3RpbmcxGjAYBgNVBAMTEXRmLWFjYy1jYS5pbnZhbGlk
MQowCAYDVQQFEwEyMB4XDTE2MDgyMjE2NDU1NloXDTI2MDgyMDE2NDU1Nlowgcsx
CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNUGlyYXRlIEhhcmJv
cjEZMBcGA1UECRMQNTg3OSBDb3R0b24gTGluazETMBEGA1UEERMKOTU1NTktMTIy
NzEVMBMGA1UEChMMRXhhbXBsZSwgSW5jMSgwJgYDVQQLEx9EZXBhcnRtZW50IG9m
IFRlcnJhZm9ybSBUZXN0aW5nMRowGAYDVQQDExF0Zi1hY2MtY2EuaW52YWxpZDEK
MAgGA1UEBRMBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7k1xdX
HdA0HTajtSPvCwIeNE4HO3IsYn9jnUBvhQ52EJ72GPzlg91AhdVufIncJRjk51iP
n86TO/bg/dx4d+G45aUFw7WmZGTTZjurhnVWCDPeeetItV3PmsWHkwTiBj4GJYW4
1mJk0ACjmmGEyz24T46Cn87Tljk+ivdCQL/oYTjpC7jc2i5b7ziiwsToWMEljWV1
cf/4qQNFmFnETbaQW2qcFdjUoO8N1gRNkC9yvOjo6Fc+lETRHn3e926jDSaqfbwJ
hKKBoXciYnddNXgA83GBTdnsRiRoD4zFEhNThmgvy5MmkEEdwKl5QIz6ajo4Xxtd
54XZpt0y/ZVy6BECAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgIEMBkGA1UdJQQSMBAG
CCsGAQUFBwMBBgRVHSUAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP4VkPlF
IexIi3dHwrIMtY70oMZLMB8GA1UdIwQYMBaAFP4VkPlFIexIi3dHwrIMtY70oMZL
MA0GCSqGSIb3DQEBCwUAA4IBAQBlXSOkvE/c8pcI6vijInnAWY+eX2W7njCzEfmP
gkDeW/2A1/6eSM6C/ym+9zEgZ9YLxPfiQKzN8Ej+EziFiZW3ZBHnWcW9rZt36wFA
swF2nIqWa5nkVnAX2aPVfULN1u1BQiv3XZqNNlBk6m9AsgxiZ9jtOY8oQQU3uDYe
bs9ttLMKJApbe08sKmPawVlXHqj6qb85Pg4bzzknA+euRee9KIi87eTlWc/Ht+WN
Huh16WqokePii7e/PAaiTAe7ubsPav29lzmHq2NooXrs+FljXveQJpBqu6wKKTXe
6/5BBsp2474RiZgTbuO2Mbr2nwcoJ9V6iu1M9siCGbbt1nQr
-----END CERTIFICATE-----
`
const testAccAWSAPIGatewayCertPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAv/FM+jPe2e+QuO2GqwwrBZW0TXKLbXRSex4FiRzbDqJBRcwK
xeTDY9ldbpAhbujUY2OesTn2OR4QnYAERjKiv6iho1maMnR29jW0V6syGw6RC50M
HP55pHXdRC8wVzjacVatLn9cIiebgeNZuUR/DZv/BsbBM/Mg3f7NZ23ZdOxLMhFR
iCNfL/3doshWFZpgOw/jlEwLjyqEkpKxg5Uf89KSDDgB+iENfOfaKW1NQEV0ZmoG
58xbiw+nwbwMg6+3TU2xcHZAstWBwwlV6DH3HGDnT5x/ogtyTkCn9LOQI3tdiTzN
YLfr9AiSJDpswzLScm2ATQGPCbCcUX7MX8DigwIDAQABAoIBAFSRcXQPpJFrDt2b
sajtTItCYVV6MVpBVRHvsUqvDwkMjiu9ccWtPDVjENpk4IYoSWOdAc9eFVEnIPTz
8W4oYzKEjusU0G6Ih92E3fd+cy4epeNzB2JC8L94OswO6oKThxNGuDjzXlmiD88T
p3WMa1pIr/2BVqCX75Q/7qoyaQwtR/anvOes154gRGY70ucsUpEzo3fyfXdCKO/o
y1quQ4mmCS50lPCJ3i8JZH2YmGY+xThnXzk7Q9ipjGrHTjinpX8f9tQB2RRwqlA/
uQ+/q6cOKUAehLtriXyr2QAoCzdz1Lfm8L5KQ3EdrxUUe9dhs/a7bKw4N5eHjw/x
eBUagsECgYEAyoaIqZ0ur5NQEHuY9Givs6a+ObWLjM18EdfQ7zX7NJRPL3q0jdkm
KW+pn2OzoRxhwgaD6WuJJmj3rd3ledkwxoO6Efwo8x2z1u/T43FsknW/X3wJLLga
fPU2T9lSHRufBQUAhPYkf4dSqUklHJ4YSMafbCkvSXKGZqGVLQfu1iECgYEA8p9s
/5+d0Pcnykau7Hp8a9z9ehHEIF+ce/wb6/6p3fgCP04FLvKqs74p9SrEnyl9uiFx
ZC9P2XhmEwNFGA+qKPaRBo4RoGeAYgCKD0BfdaGfmp6WLhO0pSnl4c06bXnvwqbD
DhhT6UvMs6m/uSufwtfCGO48yYiY1z6DqBjuHCMCgYBWJyrltHbSu8D4cgucFRiB
PPJ5DDCkIhmgYYWA7R7CvEB/OxyppvFj+RtYMYqNg8xWRH1DA7rhOw/5x4ZB8lGc
cRbrZbBp033YdkdV3r9IAoz5aoNgoaSq+Yk0KIeU2FYqRXl2FltqYL+aQgJmjR5Z
fxz8Xvy9qtlfuWcDM/e24QKBgQDGtH8mk+lCfUkfRuh4UJCaHnGSif5grS2R9ZZA
n18rpbThd9qS6reXYgUm/5Hs8KRBzqX5cS4qY4rlw2XRIPMxfU6lWbFh96KToPFx
MD1+L5JxpbRFpGnsYvYdCmHxy03r03wojRAcH7JU6o9U7j936hDTLjqmq7LRhid5
goFwlQKBgQCGxTWqQu9FJjtmjdM/ARi7CcwWT40NI8ybyebjDtElekILFMUwO+/w
M78Me3d5g/oyeS6qCfyK1f7vBb/WhxLBBegaqMGUWbRoKYD0LH5U3zkqZ9ehnDFB
vhcEnoxPD9HmdFkRduJscyzVNJ50lMuQ3uk7zwiYuS/Z7shH81xzMQ==
-----END RSA PRIVATE KEY-----
`
func testAccAWSAPIGatewayDomainNameConfigCreate(name string) string {
return fmt.Sprintf(`
resource "aws_api_gateway_domain_name" "test" {
domain_name = "%s"
certificate_body = "%v"
certificate_chain = "%v"
certificate_name = "tf-acc-apigateway-domain-name"
certificate_private_key = "%v"
}
`, name, testAccAWSAPIGatewayCertBody, testAccAWSAPIGatewayCertChain, testAccAWSAPIGatewayCertPrivateKey)
}

View File

@ -0,0 +1,47 @@
---
layout: "aws"
page_title: "AWS: aws_api_gateway_base_path_mapping"
sidebar_current: "docs-aws-resource-api-gateway-base-path-mapping"
description: |-
Connects a custom domain with a deployed API
---
# aws\_api\_gateway\_base\_path\_mapping
Connects a custom domain name registered via `aws_api_gateway_domain_name`
with a deployed API so that its methods can be called via the
custom domain name.
## Example Usage
```
resource "aws_api_gateway_deployment" "example" {
# See aws_api_gateway_rest_api_docs for how to create this
rest_api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}"
stage_name = "live"
}
resource "aws_api_gateway_domain_name" "example" {
domain_name = "example.com"
certificate_name = "example-api"
certificate_body = "${file("${path.module}/example.com/example.crt")}"
certificate_chain = "${file("${path.module}/example.com/ca.crt")}"
certificate_private_key = "${file("${path.module}/example.com/example.key")}"
}
resource "aws_api_gateway_base_path_mapping" "test" {
api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}"
stage = "${aws_api_gateway_deployment.example.stage_name}"
domain_name = "${aws_api_gateway_domain_name.example.domain_name}"
}
```
## Argument Reference
The following arguments are supported:
* `domain_name` - (Required) The already-registered domain name to connect the API to.
* `api_id` - (Required) The id of the API to connect.
* `stage` - (Optional) The name of a specific deployment stage to expose at the given path. If omitted, callers may select any stage by including its name as a path element after the base path.
* `base_path` - (Optional) Path segment that must be prepended to the path when accessing the API via this mapping. If omitted, the API is exposed at the root of the given domain.

View File

@ -0,0 +1,75 @@
---
layout: "aws"
page_title: "AWS: aws_api_gateway_domain_name"
sidebar_current: "docs-aws-resource-api-gateway-domain-name"
description: |-
Registers a custom domain name for use with AWS API Gateway.
---
# aws\_api\_gateway\_domain\_name
Registers a custom domain name for use with AWS API Gateway.
This resource just establishes ownership of and the TLS settings for
a particular domain name. An API can be attached to a particular path
under the registered domain name using
[the `aws_api_gateway_base_path_mapping` resource](api_gateway_base_path_mapping.html).
Internally API Gateway creates a CloudFront distribution to
route requests on the given hostname. In addition to this resource
it's necessary to create a DNS record corresponding to the
given domain name which is an alias (either Route53 alias or
traditional CNAME) to the Cloudfront domain name exported in the
`cloudfront_domain_name` attribute.
## Example Usage
```
resource "aws_api_gateway_domain_name" "example" {
domain_name = "api.example.com"
certificate_name = "example-api"
certificate_body = "${file("${path.module}/example.com/example.crt")}"
certificate_chain = "${file("${path.module}/example.com/ca.crt")}"
certificate_private_key = "${file("${path.module}/example.com/example.key")}"
}
# Example DNS record using Route53.
# Route53 is not specifically required; any DNS host can be used.
resource "aws_route53_record" "example" {
zone_id = "${aws_route53_zone.example.id}" # See aws_route53_zone for how to create this
name = "${aws_api_gateway_domain_name.example.domain_name}"
type = "A"
alias {
name = "${aws_api_gateway_domain_name.example.cloudfront_domain_name}"
zone_id = "${aws_api_gateway_domain_name.example.cloudfront_zone_id}"
}
}
```
## Argument Reference
The following arguments are supported:
* `domain_name` - (Required) The fully-qualified domain name to register
* `certificate_name` - (Required) The unique name to use when registering this
cert as an IAM server certificate
* `certificate_body` - (Required) The certificate issued for the domain name
being registered, in PEM format
* `certificate_chain` - (Required) The certificate for the CA that issued the
certificate, along with any intermediate CA certificates required to
create an unbroken chain to a certificate trusted by the intended API clients.
* `certificate_private_key` - (Required) The private key associated with the
domain certificate given in `certificate_body`.
## Attributes Reference
The following attributes are exported:
* `id` - The internal id assigned to this domain name by API Gateway.
* `cloudfront_domain_name` - The hostname created by Cloudfront to represent
the distribution that implements this domain name mapping.
* `cloudfront_zone_id` - For convenience, the hosted zone id (`Z2FDTNDATAQYW2`)
that can be used to create a Route53 alias record for the distribution.

View File

@ -56,9 +56,15 @@
<li<%= sidebar_current("docs-aws-resource-api-gateway-authorizer") %>> <li<%= sidebar_current("docs-aws-resource-api-gateway-authorizer") %>>
<a href="/docs/providers/aws/r/api_gateway_authorizer.html">aws_api_gateway_authorizer</a> <a href="/docs/providers/aws/r/api_gateway_authorizer.html">aws_api_gateway_authorizer</a>
</li> </li>
<li<%= sidebar_current("docs-aws-resource-api-gateway-base-path-mapping") %>>
<a href="/docs/providers/aws/r/api_gateway_base_path_mapping.html">aws_api_gateway_base_path_mapping</a>
</li>
<li<%= sidebar_current("docs-aws-resource-api-gateway-deployment") %>> <li<%= sidebar_current("docs-aws-resource-api-gateway-deployment") %>>
<a href="/docs/providers/aws/r/api_gateway_deployment.html">aws_api_gateway_deployment</a> <a href="/docs/providers/aws/r/api_gateway_deployment.html">aws_api_gateway_deployment</a>
</li> </li>
<li<%= sidebar_current("docs-aws-resource-api-gateway-domain-name") %>>
<a href="/docs/providers/aws/r/api_gateway_domain_name.html">aws_api_gateway_domain_name</a>
</li>
<li<%= sidebar_current("docs-aws-resource-api-gateway-integration") %>> <li<%= sidebar_current("docs-aws-resource-api-gateway-integration") %>>
<a href="/docs/providers/aws/r/api_gateway_integration.html">aws_api_gateway_integration</a> <a href="/docs/providers/aws/r/api_gateway_integration.html">aws_api_gateway_integration</a>
</li> </li>