diff --git a/builtin/providers/aws/resource_aws_route53_zone.go b/builtin/providers/aws/resource_aws_route53_zone.go new file mode 100644 index 000000000..eb094bf45 --- /dev/null +++ b/builtin/providers/aws/resource_aws_route53_zone.go @@ -0,0 +1,116 @@ +package aws + +import ( + "log" + "time" + + "github.com/hashicorp/terraform/helper/config" + "github.com/hashicorp/terraform/helper/diff" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/mitchellh/goamz/route53" +) + +func resource_aws_r53_zone_validation() *config.Validator { + return &config.Validator{ + Required: []string{ + "name", + }, + } +} + +func resource_aws_r53_zone_create( + s *terraform.ResourceState, + d *terraform.ResourceDiff, + meta interface{}) (*terraform.ResourceState, error) { + p := meta.(*ResourceProvider) + r53 := p.route53 + + // Merge the diff into the state so that we have all the attributes + // properly. + rs := s.MergeDiff(d) + + req := &route53.CreateHostedZoneRequest{ + Name: rs.Attributes["name"], + Comment: "Managed by Terraform", + } + log.Printf("[DEBUG] Creating Route53 hosted zone: %s", req.Name) + resp, err := r53.CreateHostedZone(req) + if err != nil { + return rs, err + } + + // Store the zone_id + zone := route53.CleanZoneID(resp.HostedZone.ID) + rs.ID = zone + rs.Attributes["zone_id"] = zone + + // Wait until we are done initializing + wait := resource.StateChangeConf{ + Pending: []string{"PENDING"}, + Target: "INSYNC", + Timeout: 10 * time.Minute, + Refresh: func() (result interface{}, state string, err error) { + return resource_aws_r53_wait(r53, resp.ChangeInfo.ID) + }, + } + _, err = wait.WaitForState() + if err != nil { + return rs, err + } + return rs, nil +} + +// resource_aws_r53_wait checks the status of a change +func resource_aws_r53_wait(r53 *route53.Route53, ref string) (result interface{}, state string, err error) { + status, err := r53.GetChange(ref) + if err != nil { + return nil, "UNKNOWN", err + } + return true, status, nil +} + +func resource_aws_r53_zone_destroy( + s *terraform.ResourceState, + meta interface{}) error { + p := meta.(*ResourceProvider) + r53 := p.route53 + + log.Printf("[DEBUG] Deleting Route53 hosted zone: %s (ID: %s)", + s.Attributes["name"], s.Attributes["zone_id"]) + _, err := r53.DeleteHostedZone(s.Attributes["zone_id"]) + if err != nil { + return err + } + return nil +} + +func resource_aws_r53_zone_refresh( + s *terraform.ResourceState, + meta interface{}) (*terraform.ResourceState, error) { + p := meta.(*ResourceProvider) + r53 := p.route53 + + _, err := r53.GetHostedZone(s.Attributes["zone_id"]) + if err != nil { + return s, err + } + return s, nil +} + +func resource_aws_r53_zone_diff( + s *terraform.ResourceState, + c *terraform.ResourceConfig, + meta interface{}) (*terraform.ResourceDiff, error) { + + b := &diff.ResourceBuilder{ + Attrs: map[string]diff.AttrType{ + "name": diff.AttrTypeCreate, + }, + + ComputedAttrs: []string{ + "zone_id", + }, + } + return b.Diff(s, c) +} diff --git a/builtin/providers/aws/resource_aws_route53_zone_test.go b/builtin/providers/aws/resource_aws_route53_zone_test.go new file mode 100644 index 000000000..0969abeb3 --- /dev/null +++ b/builtin/providers/aws/resource_aws_route53_zone_test.go @@ -0,0 +1,66 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccRoute53Zone(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRoute53ZoneDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRoute53ZoneConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRoute53ZoneExists("aws_route53_zone.main"), + ), + }, + }, + }) +} + +func testAccCheckRoute53ZoneDestroy(s *terraform.State) error { + conn := testAccProvider.route53 + for _, rs := range s.Resources { + if rs.Type != "aws_route53_zone" { + continue + } + + _, err := conn.GetHostedZone(rs.ID) + if err == nil { + return fmt.Errorf("Hosted zone still exists") + } + } + return nil +} + +func testAccCheckRoute53ZoneExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.ID == "" { + return fmt.Errorf("No hosted zone ID is set") + } + + conn := testAccProvider.route53 + _, err := conn.GetHostedZone(rs.ID) + if err != nil { + return fmt.Errorf("Hosted zone err: %v", err) + } + return nil + } +} + +const testAccRoute53ZoneConfig = ` +resource "aws_route53_zone" "main" { + name = "hashicorp.com" +} +` diff --git a/builtin/providers/aws/resource_provider.go b/builtin/providers/aws/resource_provider.go index 47b68f55a..dda9cc4c0 100644 --- a/builtin/providers/aws/resource_provider.go +++ b/builtin/providers/aws/resource_provider.go @@ -10,6 +10,7 @@ import ( "github.com/mitchellh/goamz/ec2" "github.com/mitchellh/goamz/elb" "github.com/mitchellh/goamz/rds" + "github.com/mitchellh/goamz/route53" "github.com/mitchellh/goamz/s3" ) @@ -21,6 +22,7 @@ type ResourceProvider struct { autoscalingconn *autoscaling.AutoScaling s3conn *s3.S3 rdsconn *rds.Rds + route53 *route53.Route53 } func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) { @@ -71,6 +73,8 @@ func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error { p.s3conn = s3.New(auth, region) log.Println("[INFO] Initializing RDS connection") p.rdsconn = rds.New(auth, region) + log.Println("[INFO] Initializing Route53 connection") + p.route53 = route53.New(auth, region) } if len(errs) > 0 { diff --git a/builtin/providers/aws/resources.go b/builtin/providers/aws/resources.go index 9e0ba2137..6e2c6c220 100644 --- a/builtin/providers/aws/resources.go +++ b/builtin/providers/aws/resources.go @@ -103,6 +103,14 @@ func init() { Update: resource_aws_route_table_association_update, }, + "aws_route53_zone": resource.Resource{ + ConfigValidator: resource_aws_r53_zone_validation(), + Create: resource_aws_r53_zone_create, + Destroy: resource_aws_r53_zone_destroy, + Diff: resource_aws_r53_zone_diff, + Refresh: resource_aws_r53_zone_refresh, + }, + "aws_s3_bucket": resource.Resource{ ConfigValidator: resource_aws_s3_bucket_validation(), Create: resource_aws_s3_bucket_create,