Merge pull request #1999 from TimeIncOSS/r53-delegation-set

provider/aws: Add Route 53 delegation set resource
This commit is contained in:
Radek Simko 2015-06-23 22:51:47 +01:00
commit 5cf5451d28
7 changed files with 327 additions and 2 deletions

View File

@ -126,6 +126,7 @@ func Provider() terraform.ResourceProvider {
"aws_network_acl": resourceAwsNetworkAcl(),
"aws_network_interface": resourceAwsNetworkInterface(),
"aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(),
"aws_route53_delegation_set": resourceAwsRoute53DelegationSet(),
"aws_route53_record": resourceAwsRoute53Record(),
"aws_route53_zone_association": resourceAwsRoute53ZoneAssociation(),
"aws_route53_zone": resourceAwsRoute53Zone(),

View File

@ -0,0 +1,108 @@
package aws
import (
"log"
"sort"
"strings"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53"
)
func resourceAwsRoute53DelegationSet() *schema.Resource {
return &schema.Resource{
Create: resourceAwsRoute53DelegationSetCreate,
Read: resourceAwsRoute53DelegationSetRead,
Delete: resourceAwsRoute53DelegationSetDelete,
Schema: map[string]*schema.Schema{
"reference_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"name_servers": &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
},
}
}
func resourceAwsRoute53DelegationSetCreate(d *schema.ResourceData, meta interface{}) error {
r53 := meta.(*AWSClient).r53conn
callerRef := resource.UniqueId()
if v, ok := d.GetOk("reference_name"); ok {
callerRef = strings.Join([]string{
v.(string), "-", callerRef,
}, "")
}
input := &route53.CreateReusableDelegationSetInput{
CallerReference: aws.String(callerRef),
}
log.Printf("[DEBUG] Creating Route53 reusable delegation set: %#v", input)
out, err := r53.CreateReusableDelegationSet(input)
if err != nil {
return err
}
log.Printf("[DEBUG] Route53 reusable delegation set created: %#v", out)
set := out.DelegationSet
d.SetId(cleanDelegationSetId(*set.ID))
d.Set("name_servers", expandNameServers(set.NameServers))
return nil
}
func resourceAwsRoute53DelegationSetRead(d *schema.ResourceData, meta interface{}) error {
r53 := meta.(*AWSClient).r53conn
input := &route53.GetReusableDelegationSetInput{
ID: aws.String(cleanDelegationSetId(d.Id())),
}
log.Printf("[DEBUG] Reading Route53 reusable delegation set: %#v", input)
out, err := r53.GetReusableDelegationSet(input)
if err != nil {
return err
}
log.Printf("[DEBUG] Route53 reusable delegation set received: %#v", out)
set := out.DelegationSet
d.SetId(cleanDelegationSetId(*set.ID))
d.Set("name_servers", expandNameServers(set.NameServers))
return nil
}
func resourceAwsRoute53DelegationSetDelete(d *schema.ResourceData, meta interface{}) error {
r53 := meta.(*AWSClient).r53conn
input := &route53.DeleteReusableDelegationSetInput{
ID: aws.String(cleanDelegationSetId(d.Id())),
}
log.Printf("[DEBUG] Deleting Route53 reusable delegation set: %#v", input)
_, err := r53.DeleteReusableDelegationSet(input)
return err
}
func expandNameServers(name_servers []*string) []string {
log.Printf("[DEBUG] Processing %d name servers: %#v...", len(name_servers), name_servers)
ns := make([]string, len(name_servers))
for i, server := range name_servers {
ns[i] = *server
}
sort.Strings(ns)
log.Printf("[DEBUG] Returning processed name servers: %#v", ns)
return ns
}
func cleanDelegationSetId(id string) string {
return strings.TrimPrefix(id, "/delegationset/")
}

View File

@ -0,0 +1,153 @@
package aws
import (
"fmt"
"reflect"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53"
)
func TestAccRoute53DelegationSet_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckRoute53ZoneDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccRoute53DelegationSetConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckRoute53DelegationSetExists("aws_route53_delegation_set.test"),
),
},
},
})
}
func TestAccRoute53DelegationSet_withZones(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: testAccRoute53DelegationSetWithZonesConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckRoute53DelegationSetExists("aws_route53_delegation_set.main"),
testAccCheckRoute53ZoneExists("aws_route53_zone.primary", &zone),
testAccCheckRoute53ZoneExists("aws_route53_zone.secondary", &zone),
testAccCheckRoute53NameServersMatch("aws_route53_delegation_set.main", "aws_route53_zone.primary"),
testAccCheckRoute53NameServersMatch("aws_route53_delegation_set.main", "aws_route53_zone.secondary"),
),
},
},
})
}
func testAccCheckRoute53DelegationSetDestroy(s *terraform.State, provider *schema.Provider) error {
conn := provider.Meta().(*AWSClient).r53conn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_route53_delegation_set" {
continue
}
_, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{ID: aws.String(rs.Primary.ID)})
if err == nil {
return fmt.Errorf("Delegation set still exists")
}
}
return nil
}
func testAccCheckRoute53DelegationSetExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).r53conn
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No delegation set ID is set")
}
out, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{
ID: aws.String(rs.Primary.ID),
})
if err != nil {
return fmt.Errorf("Delegation set does not exist: %#v", rs.Primary.ID)
}
setID := cleanDelegationSetId(*out.DelegationSet.ID)
if setID != rs.Primary.ID {
return fmt.Errorf("Delegation set ID does not match:\nExpected: %#v\nReturned: %#v", rs.Primary.ID, setID)
}
return nil
}
}
func testAccCheckRoute53NameServersMatch(delegationSetName, zoneName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).r53conn
delegationSetLocal, ok := s.RootModule().Resources[delegationSetName]
if !ok {
return fmt.Errorf("Not found: %s", delegationSetName)
}
delegationSet, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{
ID: aws.String(delegationSetLocal.Primary.ID),
})
if err != nil {
return fmt.Errorf("Delegation set does not exist: %#v", delegationSetLocal.Primary.ID)
}
hostedZoneLocal, ok := s.RootModule().Resources[zoneName]
if !ok {
return fmt.Errorf("Not found: %s", zoneName)
}
hostedZone, err := conn.GetHostedZone(&route53.GetHostedZoneInput{
ID: aws.String(hostedZoneLocal.Primary.ID),
})
if err != nil {
return fmt.Errorf("Delegation set does not exist: %#v", hostedZoneLocal.Primary.ID)
}
if !reflect.DeepEqual(delegationSet.DelegationSet.NameServers, hostedZone.DelegationSet.NameServers) {
return fmt.Errorf("Name servers do not match:\nDelegation Set: %#v\nHosted Zone:%#v",
delegationSet.DelegationSet.NameServers, hostedZone.DelegationSet.NameServers)
}
return nil
}
}
const testAccRoute53DelegationSetConfig = `
resource "aws_route53_delegation_set" "test" {
reference_name = "test"
}
`
const testAccRoute53DelegationSetWithZonesConfig = `
resource "aws_route53_delegation_set" "main" {
reference_name = "main"
}
resource "aws_route53_zone" "primary" {
name = "hashicorp.com"
delegation_set_id = "${aws_route53_delegation_set.main.id}"
}
resource "aws_route53_zone" "secondary" {
name = "terraform.io"
delegation_set_id = "${aws_route53_delegation_set.main.id}"
}
`

View File

@ -32,7 +32,7 @@ func resourceAwsRoute53Zone() *schema.Resource {
"comment": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "Managed by Terraform",
Default: "Managed by Terraform",
},
"vpc_id": &schema.Schema{
@ -53,6 +53,12 @@ func resourceAwsRoute53Zone() *schema.Resource {
Computed: true,
},
"delegation_set_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"name_servers": &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
@ -83,6 +89,10 @@ func resourceAwsRoute53ZoneCreate(d *schema.ResourceData, meta interface{}) erro
d.Set("vpc_region", req.VPC.VPCRegion)
}
if v, ok := d.GetOk("delegation_set_id"); ok {
req.DelegationSetID = aws.String(v.(string))
}
log.Printf("[DEBUG] Creating Route53 hosted zone: %s", *req.Name)
var err error
resp, err := r53.CreateHostedZone(req)
@ -157,6 +167,10 @@ func resourceAwsRoute53ZoneRead(d *schema.ResourceData, meta interface{}) error
}
}
if zone.DelegationSet != nil && zone.DelegationSet.ID != nil {
d.Set("delegation_set_id", cleanDelegationSetId(*zone.DelegationSet.ID))
}
// get tags
req := &route53.ListTagsForResourceInput{
ResourceID: aws.String(d.Id()),

View File

@ -0,0 +1,44 @@
---
layout: "aws"
page_title: "AWS: aws_route53_delegation_set"
sidebar_current: "docs-aws-resource-route53-delegation-set"
description: |-
Provides a Route53 Delegation Set resource.
---
# aws\_route53\_delegation_set
Provides a [Route53 Delegation Set](http://docs.aws.amazon.com/Route53/latest/APIReference/actions-on-reusable-delegation-sets.html) resource.
## Example Usage
```
resource "aws_route53_delegation_set" "main" {
reference_name = "DynDNS"
}
resource "aws_route53_zone" "primary" {
name = "hashicorp.com"
delegation_set_id = "${aws_route53_delegation_set.main.id}"
}
resource "aws_route53_zone" "secondary" {
name = "terraform.io"
delegation_set_id = "${aws_route53_delegation_set.main.id}"
}
```
## Argument Reference
The following arguments are supported:
* `reference_name` - (Optional) This is a reference name used in Caller Reference
(helpful for identifying single delegation set amongst others)
## Attributes Reference
The following attributes are exported:
* `id` - The delegation set ID
* `name_servers` - A list of authoritative name servers for the hosted zone
(effectively a list of NS records).

View File

@ -58,11 +58,12 @@ The following arguments are supported:
* `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.
* `delegation_set_id` - (Optional) The ID of the reusable delgation set whose NS records you want to assign to the hosted zone.
## 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 associated (or default) delegation set.
Find more about delegation sets in [AWS docs](http://docs.aws.amazon.com/Route53/latest/APIReference/actions-on-reusable-delegation-sets.html).

View File

@ -181,6 +181,10 @@
<a href="/docs/providers/aws/r/proxy_protocol_policy.html">aws_proxy_protocol_policy</a>
</li>
<li<%= sidebar_current("docs-aws-resource-route53-delegation-set") %>>
<a href="/docs/providers/aws/r/route53_delegation_set.html">aws_route53_delegation_set</a>
</li>
<li<%= sidebar_current("docs-aws-resource-route53-health-check") %>>
<a href="/docs/providers/aws/r/route53_health_check.html">aws_route53_health_check</a>
</li>