github.com/i0n/terraform@v0.4.3-0.20150506151324-010a39a58ec1/builtin/providers/aws/resource_aws_route53_zone.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sort"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  
    13  	"github.com/awslabs/aws-sdk-go/aws"
    14  	"github.com/awslabs/aws-sdk-go/service/route53"
    15  )
    16  
    17  func resourceAwsRoute53Zone() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceAwsRoute53ZoneCreate,
    20  		Read:   resourceAwsRoute53ZoneRead,
    21  		Update: resourceAwsRoute53ZoneUpdate,
    22  		Delete: resourceAwsRoute53ZoneDelete,
    23  
    24  		Schema: map[string]*schema.Schema{
    25  			"name": &schema.Schema{
    26  				Type:     schema.TypeString,
    27  				Required: true,
    28  				ForceNew: true,
    29  			},
    30  
    31  			"zone_id": &schema.Schema{
    32  				Type:     schema.TypeString,
    33  				Computed: true,
    34  			},
    35  
    36  			"name_servers": &schema.Schema{
    37  				Type:     schema.TypeList,
    38  				Elem:     &schema.Schema{Type: schema.TypeString},
    39  				Computed: true,
    40  			},
    41  
    42  			"tags": tagsSchema(),
    43  		},
    44  	}
    45  }
    46  
    47  func resourceAwsRoute53ZoneCreate(d *schema.ResourceData, meta interface{}) error {
    48  	r53 := meta.(*AWSClient).r53conn
    49  
    50  	comment := &route53.HostedZoneConfig{Comment: aws.String("Managed by Terraform")}
    51  	req := &route53.CreateHostedZoneInput{
    52  		Name:             aws.String(d.Get("name").(string)),
    53  		HostedZoneConfig: comment,
    54  		CallerReference:  aws.String(time.Now().Format(time.RFC3339Nano)),
    55  	}
    56  
    57  	log.Printf("[DEBUG] Creating Route53 hosted zone: %s", *req.Name)
    58  	resp, err := r53.CreateHostedZone(req)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	// Store the zone_id
    64  	zone := cleanZoneID(*resp.HostedZone.ID)
    65  	d.Set("zone_id", zone)
    66  	d.SetId(zone)
    67  
    68  	// Wait until we are done initializing
    69  	wait := resource.StateChangeConf{
    70  		Delay:      30 * time.Second,
    71  		Pending:    []string{"PENDING"},
    72  		Target:     "INSYNC",
    73  		Timeout:    10 * time.Minute,
    74  		MinTimeout: 2 * time.Second,
    75  		Refresh: func() (result interface{}, state string, err error) {
    76  			changeRequest := &route53.GetChangeInput{
    77  				ID: aws.String(cleanChangeID(*resp.ChangeInfo.ID)),
    78  			}
    79  			return resourceAwsGoRoute53Wait(r53, changeRequest)
    80  		},
    81  	}
    82  	_, err = wait.WaitForState()
    83  	if err != nil {
    84  		return err
    85  	}
    86  	return resourceAwsRoute53ZoneUpdate(d, meta)
    87  }
    88  
    89  func resourceAwsRoute53ZoneRead(d *schema.ResourceData, meta interface{}) error {
    90  	r53 := meta.(*AWSClient).r53conn
    91  	zone, err := r53.GetHostedZone(&route53.GetHostedZoneInput{ID: aws.String(d.Id())})
    92  	if err != nil {
    93  		// Handle a deleted zone
    94  		if r53err, ok := err.(aws.APIError); ok && r53err.Code == "NoSuchHostedZone" {
    95  			d.SetId("")
    96  			return nil
    97  		}
    98  		return err
    99  	}
   100  
   101  	ns := make([]string, len(zone.DelegationSet.NameServers))
   102  	for i := range zone.DelegationSet.NameServers {
   103  		ns[i] = *zone.DelegationSet.NameServers[i]
   104  	}
   105  	sort.Strings(ns)
   106  	if err := d.Set("name_servers", ns); err != nil {
   107  		return fmt.Errorf("[DEBUG] Error setting name servers for: %s, error: %#v", d.Id(), err)
   108  	}
   109  
   110  	// get tags
   111  	req := &route53.ListTagsForResourceInput{
   112  		ResourceID:   aws.String(d.Id()),
   113  		ResourceType: aws.String("hostedzone"),
   114  	}
   115  
   116  	resp, err := r53.ListTagsForResource(req)
   117  	if err != nil {
   118  		return err
   119  	}
   120  
   121  	var tags []*route53.Tag
   122  	if resp.ResourceTagSet != nil {
   123  		tags = resp.ResourceTagSet.Tags
   124  	}
   125  
   126  	if err := d.Set("tags", tagsToMapR53(tags)); err != nil {
   127  		return err
   128  	}
   129  
   130  	return nil
   131  }
   132  
   133  func resourceAwsRoute53ZoneUpdate(d *schema.ResourceData, meta interface{}) error {
   134  	conn := meta.(*AWSClient).r53conn
   135  
   136  	if err := setTagsR53(conn, d); err != nil {
   137  		return err
   138  	} else {
   139  		d.SetPartial("tags")
   140  	}
   141  
   142  	return resourceAwsRoute53ZoneRead(d, meta)
   143  }
   144  
   145  func resourceAwsRoute53ZoneDelete(d *schema.ResourceData, meta interface{}) error {
   146  	r53 := meta.(*AWSClient).r53conn
   147  
   148  	log.Printf("[DEBUG] Deleting Route53 hosted zone: %s (ID: %s)",
   149  		d.Get("name").(string), d.Id())
   150  	_, err := r53.DeleteHostedZone(&route53.DeleteHostedZoneInput{ID: aws.String(d.Id())})
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	return nil
   156  }
   157  
   158  func resourceAwsGoRoute53Wait(r53 *route53.Route53, ref *route53.GetChangeInput) (result interface{}, state string, err error) {
   159  
   160  	status, err := r53.GetChange(ref)
   161  	if err != nil {
   162  		return nil, "UNKNOWN", err
   163  	}
   164  	return true, *status.ChangeInfo.Status, nil
   165  }
   166  
   167  // cleanChangeID is used to remove the leading /change/
   168  func cleanChangeID(ID string) string {
   169  	return cleanPrefix(ID, "/change/")
   170  }
   171  
   172  // cleanZoneID is used to remove the leading /hostedzone/
   173  func cleanZoneID(ID string) string {
   174  	return cleanPrefix(ID, "/hostedzone/")
   175  }
   176  
   177  // cleanPrefix removes a string prefix from an ID
   178  func cleanPrefix(ID, prefix string) string {
   179  	if strings.HasPrefix(ID, prefix) {
   180  		ID = strings.TrimPrefix(ID, prefix)
   181  	}
   182  	return ID
   183  }