Merge pull request #1526 from PeopleNet/route53_private_hosted_zone
AWS/Route53Zone - create private hosted zone associated with VPC.
This commit is contained in:
commit
b3a4965f84
|
@ -9,12 +9,14 @@ IMPROVEMENTS:
|
|||
|
||||
* **New config function: `formatlist`** - Format lists in a similar way to `format`.
|
||||
Useful for creating URLs from a list of IPs. [GH-1829]
|
||||
* **New resource: `aws_route53_zone_association`**
|
||||
* provider/aws: `aws_autoscaling_group` can wait for capacity in ELB
|
||||
via `min_elb_capacity` [GH-1970]
|
||||
* provider/aws: `aws_db_instances` supports `license_model` [GH-1966]
|
||||
* provider/aws: `aws_elasticache_cluster` add support for Tags [GH-1965]
|
||||
* provider/aws: `aws_s3_bucket` exports `hosted_zone_id` and `region` [GH-1865]
|
||||
* provider/aws: `aws_route53_record` exports `fqdn` [GH-1847]
|
||||
* provider/aws: `aws_route53_zone` can create private hosted zones [GH-1526]
|
||||
* provider/google: `google_compute_instance` `scratch` attribute added [GH-1920]
|
||||
|
||||
BUG FIXES:
|
||||
|
|
|
@ -115,6 +115,7 @@ func Provider() terraform.ResourceProvider {
|
|||
"aws_network_interface": resourceAwsNetworkInterface(),
|
||||
"aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(),
|
||||
"aws_route53_record": resourceAwsRoute53Record(),
|
||||
"aws_route53_zone_association": resourceAwsRoute53ZoneAssociation(),
|
||||
"aws_route53_zone": resourceAwsRoute53Zone(),
|
||||
"aws_route_table_association": resourceAwsRouteTableAssociation(),
|
||||
"aws_route_table": resourceAwsRouteTable(),
|
||||
|
|
|
@ -28,6 +28,19 @@ func resourceAwsRoute53Zone() *schema.Resource {
|
|||
ForceNew: true,
|
||||
},
|
||||
|
||||
"vpc_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"vpc_region": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"zone_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
|
@ -53,6 +66,16 @@ func resourceAwsRoute53ZoneCreate(d *schema.ResourceData, meta interface{}) erro
|
|||
HostedZoneConfig: comment,
|
||||
CallerReference: aws.String(time.Now().Format(time.RFC3339Nano)),
|
||||
}
|
||||
if v := d.Get("vpc_id"); v != "" {
|
||||
req.VPC = &route53.VPC{
|
||||
VPCID: aws.String(v.(string)),
|
||||
VPCRegion: aws.String(meta.(*AWSClient).region),
|
||||
}
|
||||
if w := d.Get("vpc_region"); w != "" {
|
||||
req.VPC.VPCRegion = aws.String(w.(string))
|
||||
}
|
||||
d.Set("vpc_region", req.VPC.VPCRegion)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Creating Route53 hosted zone: %s", *req.Name)
|
||||
resp, err := r53.CreateHostedZone(req)
|
||||
|
@ -98,13 +121,33 @@ func resourceAwsRoute53ZoneRead(d *schema.ResourceData, meta interface{}) error
|
|||
return err
|
||||
}
|
||||
|
||||
ns := make([]string, len(zone.DelegationSet.NameServers))
|
||||
for i := range zone.DelegationSet.NameServers {
|
||||
ns[i] = *zone.DelegationSet.NameServers[i]
|
||||
}
|
||||
sort.Strings(ns)
|
||||
if err := d.Set("name_servers", ns); err != nil {
|
||||
return fmt.Errorf("[DEBUG] Error setting name servers for: %s, error: %#v", d.Id(), err)
|
||||
if !*zone.HostedZone.Config.PrivateZone {
|
||||
ns := make([]string, len(zone.DelegationSet.NameServers))
|
||||
for i := range zone.DelegationSet.NameServers {
|
||||
ns[i] = *zone.DelegationSet.NameServers[i]
|
||||
}
|
||||
sort.Strings(ns)
|
||||
if err := d.Set("name_servers", ns); err != nil {
|
||||
return fmt.Errorf("[DEBUG] Error setting name servers for: %s, error: %#v", d.Id(), err)
|
||||
}
|
||||
} else {
|
||||
ns, err := getNameServers(d.Id(), d.Get("name").(string), r53)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set("name_servers", ns); err != nil {
|
||||
return fmt.Errorf("[DEBUG] Error setting name servers for: %s, error: %#v", d.Id(), err)
|
||||
}
|
||||
|
||||
var associatedVPC *route53.VPC
|
||||
for _, vpc := range zone.VPCs {
|
||||
if *vpc.VPCID == d.Get("vpc_id") {
|
||||
associatedVPC = vpc
|
||||
}
|
||||
}
|
||||
if associatedVPC == nil {
|
||||
return fmt.Errorf("[DEBUG] VPC: %v is not associated with Zone: %v", d.Get("vpc_id"), d.Id())
|
||||
}
|
||||
}
|
||||
|
||||
// get tags
|
||||
|
@ -181,3 +224,23 @@ func cleanPrefix(ID, prefix string) string {
|
|||
}
|
||||
return ID
|
||||
}
|
||||
|
||||
func getNameServers(zoneId string, zoneName string, r53 *route53.Route53) ([]string, error) {
|
||||
resp, err := r53.ListResourceRecordSets(&route53.ListResourceRecordSetsInput{
|
||||
HostedZoneID: aws.String(zoneId),
|
||||
StartRecordName: aws.String(zoneName),
|
||||
StartRecordType: aws.String("NS"),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(resp.ResourceRecordSets) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
ns := make([]string, len(resp.ResourceRecordSets[0].ResourceRecords))
|
||||
for i := range resp.ResourceRecordSets[0].ResourceRecords {
|
||||
ns[i] = *resp.ResourceRecordSets[0].ResourceRecords[i].Value
|
||||
}
|
||||
sort.Strings(ns)
|
||||
return ns, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
||||
"github.com/awslabs/aws-sdk-go/aws"
|
||||
"github.com/awslabs/aws-sdk-go/service/route53"
|
||||
)
|
||||
|
||||
func resourceAwsRoute53ZoneAssociation() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsRoute53ZoneAssociationCreate,
|
||||
Read: resourceAwsRoute53ZoneAssociationRead,
|
||||
Update: resourceAwsRoute53ZoneAssociationUpdate,
|
||||
Delete: resourceAwsRoute53ZoneAssociationDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"zone_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"vpc_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"vpc_region": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsRoute53ZoneAssociationCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
r53 := meta.(*AWSClient).r53conn
|
||||
|
||||
req := &route53.AssociateVPCWithHostedZoneInput{
|
||||
HostedZoneID: aws.String(d.Get("zone_id").(string)),
|
||||
VPC: &route53.VPC{
|
||||
VPCID: aws.String(d.Get("vpc_id").(string)),
|
||||
VPCRegion: aws.String(meta.(*AWSClient).region),
|
||||
},
|
||||
Comment: aws.String("Managed by Terraform"),
|
||||
}
|
||||
if w := d.Get("vpc_region"); w != "" {
|
||||
req.VPC.VPCRegion = aws.String(w.(string))
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Associating Route53 Private Zone %s with VPC %s with region %s", *req.HostedZoneID, *req.VPC.VPCID, *req.VPC.VPCRegion)
|
||||
resp, err := r53.AssociateVPCWithHostedZone(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Store association id
|
||||
d.SetId(fmt.Sprintf("%s:%s", *req.HostedZoneID, *req.VPC.VPCID))
|
||||
d.Set("vpc_region", req.VPC.VPCRegion)
|
||||
|
||||
// Wait until we are done initializing
|
||||
wait := resource.StateChangeConf{
|
||||
Delay: 30 * time.Second,
|
||||
Pending: []string{"PENDING"},
|
||||
Target: "INSYNC",
|
||||
Timeout: 10 * time.Minute,
|
||||
MinTimeout: 2 * time.Second,
|
||||
Refresh: func() (result interface{}, state string, err error) {
|
||||
changeRequest := &route53.GetChangeInput{
|
||||
ID: aws.String(cleanChangeID(*resp.ChangeInfo.ID)),
|
||||
}
|
||||
return resourceAwsGoRoute53Wait(r53, changeRequest)
|
||||
},
|
||||
}
|
||||
_, err = wait.WaitForState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceAwsRoute53ZoneAssociationUpdate(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsRoute53ZoneAssociationRead(d *schema.ResourceData, meta interface{}) error {
|
||||
r53 := meta.(*AWSClient).r53conn
|
||||
zone_id, vpc_id := resourceAwsRoute53ZoneAssociationParseId(d.Id())
|
||||
zone, err := r53.GetHostedZone(&route53.GetHostedZoneInput{ID: aws.String(zone_id)})
|
||||
if err != nil {
|
||||
// Handle a deleted zone
|
||||
if r53err, ok := err.(aws.APIError); ok && r53err.Code == "NoSuchHostedZone" {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for _, vpc := range zone.VPCs {
|
||||
if vpc_id == *vpc.VPCID {
|
||||
// association is there, return
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// no association found
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsRoute53ZoneAssociationUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
return resourceAwsRoute53ZoneAssociationRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsRoute53ZoneAssociationDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
r53 := meta.(*AWSClient).r53conn
|
||||
zone_id, vpc_id := resourceAwsRoute53ZoneAssociationParseId(d.Id())
|
||||
log.Printf("[DEBUG] Deleting Route53 Private Zone (%s) association (VPC: %s)",
|
||||
zone_id, vpc_id)
|
||||
|
||||
req := &route53.DisassociateVPCFromHostedZoneInput{
|
||||
HostedZoneID: aws.String(zone_id),
|
||||
VPC: &route53.VPC{
|
||||
VPCID: aws.String(vpc_id),
|
||||
VPCRegion: aws.String(d.Get("vpc_region").(string)),
|
||||
},
|
||||
Comment: aws.String("Managed by Terraform"),
|
||||
}
|
||||
|
||||
_, err := r53.DisassociateVPCFromHostedZone(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsRoute53ZoneAssociationParseId(id string) (zone_id, vpc_id string) {
|
||||
parts := strings.SplitN(id, ":", 2)
|
||||
zone_id = parts[0]
|
||||
vpc_id = parts[1]
|
||||
return
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
|
||||
"github.com/awslabs/aws-sdk-go/aws"
|
||||
"github.com/awslabs/aws-sdk-go/service/route53"
|
||||
)
|
||||
|
||||
func TestAccRoute53ZoneAssociation_basic(t *testing.T) {
|
||||
var zone route53.HostedZone
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckRoute53ZoneAssociationDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccRoute53ZoneAssociationConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckRoute53ZoneAssociationExists("aws_route53_zone_association.foobar", &zone),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccRoute53ZoneAssociation_region(t *testing.T) {
|
||||
var zone route53.HostedZone
|
||||
|
||||
// record the initialized providers so that we can use them to
|
||||
// check for the instances in each region
|
||||
var providers []*schema.Provider
|
||||
providerFactories := map[string]terraform.ResourceProviderFactory{
|
||||
"aws": func() (terraform.ResourceProvider, error) {
|
||||
p := Provider()
|
||||
providers = append(providers, p.(*schema.Provider))
|
||||
return p, nil
|
||||
},
|
||||
}
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
ProviderFactories: providerFactories,
|
||||
CheckDestroy: testAccCheckRoute53ZoneAssociationDestroyWithProviders(&providers),
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccRoute53ZoneAssociationRegionConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckRoute53ZoneAssociationExistsWithProviders("aws_route53_zone_association.foobar", &zone, &providers),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneAssociationDestroy(s *terraform.State) error {
|
||||
return testAccCheckRoute53ZoneAssociationDestroyWithProvider(s, testAccProvider)
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneAssociationDestroyWithProviders(providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
for _, provider := range *providers {
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
if err := testAccCheckRoute53ZoneAssociationDestroyWithProvider(s, provider); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneAssociationDestroyWithProvider(s *terraform.State, provider *schema.Provider) error {
|
||||
conn := provider.Meta().(*AWSClient).r53conn
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_route53_zone_association" {
|
||||
continue
|
||||
}
|
||||
|
||||
zone_id, vpc_id := resourceAwsRoute53ZoneAssociationParseId(rs.Primary.ID)
|
||||
|
||||
resp, err := conn.GetHostedZone(&route53.GetHostedZoneInput{ID: aws.String(zone_id)})
|
||||
if err != nil {
|
||||
exists := false
|
||||
for _, vpc := range resp.VPCs {
|
||||
if vpc_id == *vpc.VPCID {
|
||||
exists = true
|
||||
}
|
||||
}
|
||||
if exists {
|
||||
return fmt.Errorf("VPC: %v is still associated to HostedZone: %v", vpc_id, zone_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneAssociationExists(n string, zone *route53.HostedZone) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
return testAccCheckRoute53ZoneAssociationExistsWithProvider(s, n, zone, testAccProvider)
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneAssociationExistsWithProviders(n string, zone *route53.HostedZone, providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
for _, provider := range *providers {
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
if err := testAccCheckRoute53ZoneAssociationExistsWithProvider(s, n, zone, provider); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneAssociationExistsWithProvider(s *terraform.State, n string, zone *route53.HostedZone, provider *schema.Provider) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No zone association ID is set")
|
||||
}
|
||||
|
||||
zone_id, vpc_id := resourceAwsRoute53ZoneAssociationParseId(rs.Primary.ID)
|
||||
|
||||
conn := provider.Meta().(*AWSClient).r53conn
|
||||
resp, err := conn.GetHostedZone(&route53.GetHostedZoneInput{ID: aws.String(zone_id)})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Hosted zone err: %v", err)
|
||||
}
|
||||
|
||||
exists := false
|
||||
for _, vpc := range resp.VPCs {
|
||||
if vpc_id == *vpc.VPCID {
|
||||
exists = true
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("Hosted zone association not found")
|
||||
}
|
||||
|
||||
*zone = *resp.HostedZone
|
||||
return nil
|
||||
}
|
||||
|
||||
const testAccRoute53ZoneAssociationConfig = `
|
||||
resource "aws_vpc" "foo" {
|
||||
cidr_block = "10.6.0.0/16"
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
}
|
||||
|
||||
resource "aws_vpc" "bar" {
|
||||
cidr_block = "10.7.0.0/16"
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
}
|
||||
|
||||
resource "aws_route53_zone" "foo" {
|
||||
name = "foo.com"
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
}
|
||||
|
||||
resource "aws_route53_zone_association" "foobar" {
|
||||
zone_id = "${aws_route53_zone.foo.id}"
|
||||
vpc_id = "${aws_vpc.bar.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccRoute53ZoneAssociationRegionConfig = `
|
||||
provider "aws" {
|
||||
alias = "west"
|
||||
region = "us-west-2"
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
alias = "east"
|
||||
region = "us-east-1"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "foo" {
|
||||
provider = "aws.west"
|
||||
cidr_block = "10.6.0.0/16"
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
}
|
||||
|
||||
resource "aws_vpc" "bar" {
|
||||
provider = "aws.east"
|
||||
cidr_block = "10.7.0.0/16"
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
}
|
||||
|
||||
resource "aws_route53_zone" "foo" {
|
||||
provider = "aws.west"
|
||||
name = "foo.com"
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
}
|
||||
|
||||
resource "aws_route53_zone_association" "foobar" {
|
||||
provider = "aws.west"
|
||||
zone_id = "${aws_route53_zone.foo.id}"
|
||||
vpc_id = "${aws_vpc.bar.id}"
|
||||
vpc_region = "us-east-1"
|
||||
}
|
||||
`
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
|
||||
"github.com/awslabs/aws-sdk-go/aws"
|
||||
|
@ -63,8 +64,8 @@ func TestCleanChangeID(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAccRoute53Zone(t *testing.T) {
|
||||
var zone route53.HostedZone
|
||||
func TestAccRoute53Zone_basic(t *testing.T) {
|
||||
var zone route53.GetHostedZoneOutput
|
||||
var td route53.ResourceTagSet
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
|
@ -84,8 +85,75 @@ func TestAccRoute53Zone(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccRoute53Zone_private_basic(t *testing.T) {
|
||||
var zone route53.GetHostedZoneOutput
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckRoute53ZoneDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccRoute53PrivateZoneConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckRoute53ZoneExists("aws_route53_zone.main", &zone),
|
||||
testAccCheckRoute53ZoneAssociatesWithVpc("aws_vpc.main", &zone),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccRoute53Zone_private_region(t *testing.T) {
|
||||
var zone route53.GetHostedZoneOutput
|
||||
|
||||
// record the initialized providers so that we can use them to
|
||||
// check for the instances in each region
|
||||
var providers []*schema.Provider
|
||||
providerFactories := map[string]terraform.ResourceProviderFactory{
|
||||
"aws": func() (terraform.ResourceProvider, error) {
|
||||
p := Provider()
|
||||
providers = append(providers, p.(*schema.Provider))
|
||||
return p, nil
|
||||
},
|
||||
}
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
ProviderFactories: providerFactories,
|
||||
CheckDestroy: testAccCheckRoute53ZoneDestroyWithProviders(&providers),
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccRoute53PrivateZoneRegionConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckRoute53ZoneExistsWithProviders("aws_route53_zone.main", &zone, &providers),
|
||||
testAccCheckRoute53ZoneAssociatesWithVpc("aws_vpc.main", &zone),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneDestroy(s *terraform.State) error {
|
||||
conn := testAccProvider.Meta().(*AWSClient).r53conn
|
||||
return testAccCheckRoute53ZoneDestroyWithProvider(s, testAccProvider)
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneDestroyWithProviders(providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
for _, provider := range *providers {
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
if err := testAccCheckRoute53ZoneDestroyWithProvider(s, provider); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneDestroyWithProvider(s *terraform.State, provider *schema.Provider) error {
|
||||
conn := provider.Meta().(*AWSClient).r53conn
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_route53_zone" {
|
||||
continue
|
||||
|
@ -99,23 +167,43 @@ func testAccCheckRoute53ZoneDestroy(s *terraform.State) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneExists(n string, zone *route53.HostedZone) resource.TestCheckFunc {
|
||||
func testAccCheckRoute53ZoneExists(n string, zone *route53.GetHostedZoneOutput) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
return testAccCheckRoute53ZoneExistsWithProvider(s, n, zone, testAccProvider)
|
||||
}
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No hosted zone ID is set")
|
||||
func testAccCheckRoute53ZoneExistsWithProviders(n string, zone *route53.GetHostedZoneOutput, providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
for _, provider := range *providers {
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
if err := testAccCheckRoute53ZoneExistsWithProvider(s, n, zone, provider); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AWSClient).r53conn
|
||||
resp, err := conn.GetHostedZone(&route53.GetHostedZoneInput{ID: aws.String(rs.Primary.ID)})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Hosted zone err: %v", err)
|
||||
}
|
||||
func testAccCheckRoute53ZoneExistsWithProvider(s *terraform.State, n string, zone *route53.GetHostedZoneOutput, provider *schema.Provider) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No hosted zone ID is set")
|
||||
}
|
||||
|
||||
conn := provider.Meta().(*AWSClient).r53conn
|
||||
resp, err := conn.GetHostedZone(&route53.GetHostedZoneInput{ID: aws.String(rs.Primary.ID)})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Hosted zone err: %v", err)
|
||||
}
|
||||
|
||||
if !*resp.HostedZone.Config.PrivateZone {
|
||||
sorted_ns := make([]string, len(resp.DelegationSet.NameServers))
|
||||
for i, ns := range resp.DelegationSet.NameServers {
|
||||
sorted_ns[i] = *ns
|
||||
|
@ -128,17 +216,41 @@ func testAccCheckRoute53ZoneExists(n string, zone *route53.HostedZone) resource.
|
|||
return fmt.Errorf("Got: %v for %v, Expected: %v", dsns, attribute, ns)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*zone = *resp.HostedZone
|
||||
*zone = *resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckRoute53ZoneAssociatesWithVpc(n string, zone *route53.GetHostedZoneOutput) 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 VPC ID is set")
|
||||
}
|
||||
|
||||
var associatedVPC *route53.VPC
|
||||
for _, vpc := range zone.VPCs {
|
||||
if *vpc.VPCID == rs.Primary.ID {
|
||||
associatedVPC = vpc
|
||||
}
|
||||
}
|
||||
if associatedVPC == nil {
|
||||
return fmt.Errorf("VPC: %v is not associated to Zone: %v", n, cleanZoneID(*zone.HostedZone.ID))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccLoadTagsR53(zone *route53.HostedZone, td *route53.ResourceTagSet) resource.TestCheckFunc {
|
||||
func testAccLoadTagsR53(zone *route53.GetHostedZoneOutput, td *route53.ResourceTagSet) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
conn := testAccProvider.Meta().(*AWSClient).r53conn
|
||||
|
||||
zone := cleanZoneID(*zone.ID)
|
||||
zone := cleanZoneID(*zone.HostedZone.ID)
|
||||
req := &route53.ListTagsForResourceInput{
|
||||
ResourceID: aws.String(zone),
|
||||
ResourceType: aws.String("hostedzone"),
|
||||
|
@ -167,3 +279,44 @@ resource "aws_route53_zone" "main" {
|
|||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccRoute53PrivateZoneConfig = `
|
||||
resource "aws_vpc" "main" {
|
||||
cidr_block = "172.29.0.0/24"
|
||||
instance_tenancy = "default"
|
||||
enable_dns_support = true
|
||||
enable_dns_hostnames = true
|
||||
}
|
||||
|
||||
resource "aws_route53_zone" "main" {
|
||||
name = "hashicorp.com"
|
||||
vpc_id = "${aws_vpc.main.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccRoute53PrivateZoneRegionConfig = `
|
||||
provider "aws" {
|
||||
alias = "west"
|
||||
region = "us-west-2"
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
alias = "east"
|
||||
region = "us-east-1"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "main" {
|
||||
provider = "aws.east"
|
||||
cidr_block = "172.29.0.0/24"
|
||||
instance_tenancy = "default"
|
||||
enable_dns_support = true
|
||||
enable_dns_hostnames = true
|
||||
}
|
||||
|
||||
resource "aws_route53_zone" "main" {
|
||||
provider = "aws.west"
|
||||
name = "hashicorp.com"
|
||||
vpc_id = "${aws_vpc.main.id}"
|
||||
vpc_region = "us-east-1"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -49,17 +49,23 @@ resource "aws_route53_record" "dev-ns" {
|
|||
}
|
||||
```
|
||||
|
||||
~> **NOTE:** The `name_servers` set is populated only for public Hosted Zones.
|
||||
Private Zones will contain any empty set since AWS does not return a `DelegationSet`
|
||||
for private Hosted Zones.
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Required) This is the name of the hosted zone.
|
||||
* `tags` - (Optional) A mapping of tags to assign to the zone.
|
||||
* `vpc_id` - (Optional) The VPC to associate with a private hosted zone. Specifying `vpc_id` will create a private hosted zone.
|
||||
* `vpc_region` - (Optional) The VPC's region. Defaults to the region of the AWS provider.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `zone_id` - The Hosted Zone ID. This can be referenced by zone records.
|
||||
* `name_servers` - A list of name servers in a default delegation set.
|
||||
* `name_servers` - A list of name servers in a default delegation set. Supported only for Public Hosted Zones.
|
||||
Find more about delegation sets in [AWS docs](http://docs.aws.amazon.com/Route53/latest/APIReference/actions-on-reusable-delegation-sets.html).
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_route53_zone_association"
|
||||
sidebar_current: "docs-aws-resource-route53-zone-association"
|
||||
description: |-
|
||||
Provides a Route53 private Hosted Zone to VPC association resource.
|
||||
---
|
||||
|
||||
# aws\_route53\_zone\_association
|
||||
|
||||
Provides a Route53 private Hosted Zone to VPC association resource.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
resource "aws_vpc" "primary" {
|
||||
cidr_block = "10.6.0.0/16"
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
}
|
||||
|
||||
resource "aws_vpc" "secondary" {
|
||||
cidr_block = "10.7.0.0/16"
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
}
|
||||
|
||||
resource "aws_route53_zone" "example" {
|
||||
name = "example.com"
|
||||
vpc_id = "${aws_vpc.primary.id}"
|
||||
}
|
||||
|
||||
resource "aws_route53_zone_assocation" "secondary" {
|
||||
zone_id = "${aws_route53_zone.example.id}"
|
||||
vpc_id = "${aws_vpc.secondary.id}"
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `zone_id` - (Required) The private hosted zone to associate.
|
||||
* `vpc_id` - (Required) The VPC to associate with the private hosted zone.
|
||||
* `vpc_region` - (Optional) The VPC's region. Defaults to the region of the AWS provider.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `id` - The calculated unique identifier for the association.
|
||||
* `zone_id` - The ID of the hosted zone for the association.
|
||||
* `vpc_id` - The ID of the VPC for the association.
|
||||
* `vpc_region` - The region in which the VPC identified by `vpc_id` was created.
|
|
@ -144,6 +144,10 @@
|
|||
<a href="/docs/providers/aws/r/route53_zone.html">aws_route53_zone</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-route53-zone-association") %>>
|
||||
<a href="/docs/providers/aws/r/route53_zone_association.html">aws_route53_zone_association</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-s3-bucket") %>>
|
||||
<a href="/docs/providers/aws/r/s3_bucket.html">aws_s3_bucket</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue