github.com/ezbercih/terraform@v0.1.1-0.20140729011846-3c33865e0839/builtin/providers/aws/resource_aws_route53_record.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/hashicorp/terraform/flatmap"
    11  	"github.com/hashicorp/terraform/helper/config"
    12  	"github.com/hashicorp/terraform/helper/diff"
    13  	"github.com/hashicorp/terraform/helper/resource"
    14  	"github.com/hashicorp/terraform/terraform"
    15  	"github.com/mitchellh/goamz/route53"
    16  )
    17  
    18  func resource_aws_r53_record_validation() *config.Validator {
    19  	return &config.Validator{
    20  		Required: []string{
    21  			"zone_id",
    22  			"name",
    23  			"type",
    24  			"ttl",
    25  			"records.*",
    26  		},
    27  	}
    28  }
    29  
    30  func resource_aws_r53_record_create(
    31  	s *terraform.ResourceState,
    32  	d *terraform.ResourceDiff,
    33  	meta interface{}) (*terraform.ResourceState, error) {
    34  	p := meta.(*ResourceProvider)
    35  	conn := p.route53
    36  
    37  	// Merge the diff into the state so that we have all the attributes
    38  	// properly.
    39  	rs := s.MergeDiff(d)
    40  
    41  	// Get the record
    42  	rec, err := resource_aws_r53_build_record_set(rs)
    43  	if err != nil {
    44  		return rs, err
    45  	}
    46  
    47  	// Create the new records
    48  	req := &route53.ChangeResourceRecordSetsRequest{
    49  		Comment: "Managed by Terraform",
    50  		Changes: []route53.Change{
    51  			route53.Change{
    52  				Action: "UPSERT",
    53  				Record: *rec,
    54  			},
    55  		},
    56  	}
    57  	zone := rs.Attributes["zone_id"]
    58  	log.Printf("[DEBUG] Creating resource records for zone: %s, name: %s",
    59  		zone, rs.Attributes["name"])
    60  	resp, err := conn.ChangeResourceRecordSets(zone, req)
    61  	if err != nil {
    62  		return rs, err
    63  	}
    64  
    65  	// Generate an ID
    66  	rs.ID = fmt.Sprintf("%s_%s_%s", zone, rs.Attributes["name"], rs.Attributes["type"])
    67  	rs.Dependencies = []terraform.ResourceDependency{
    68  		terraform.ResourceDependency{ID: zone},
    69  	}
    70  
    71  	// Wait until we are done
    72  	wait := resource.StateChangeConf{
    73  		Delay:      30 * time.Second,
    74  		Pending:    []string{"PENDING"},
    75  		Target:     "INSYNC",
    76  		Timeout:    10 * time.Minute,
    77  		MinTimeout: 5 * time.Second,
    78  		Refresh: func() (result interface{}, state string, err error) {
    79  			return resource_aws_r53_wait(conn, resp.ChangeInfo.ID)
    80  		},
    81  	}
    82  	_, err = wait.WaitForState()
    83  	if err != nil {
    84  		return rs, err
    85  	}
    86  	return rs, nil
    87  }
    88  
    89  func resource_aws_r53_build_record_set(s *terraform.ResourceState) (*route53.ResourceRecordSet, error) {
    90  	// Parse the TTL
    91  	ttl, err := strconv.ParseInt(s.Attributes["ttl"], 10, 32)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	// Expand the records
    97  	recRaw := flatmap.Expand(s.Attributes, "records")
    98  	var records []string
    99  	for _, raw := range recRaw.([]interface{}) {
   100  		records = append(records, raw.(string))
   101  	}
   102  
   103  	rec := &route53.ResourceRecordSet{
   104  		Name:    s.Attributes["name"],
   105  		Type:    s.Attributes["type"],
   106  		TTL:     int(ttl),
   107  		Records: records,
   108  	}
   109  	return rec, nil
   110  }
   111  
   112  func resource_aws_r53_record_destroy(
   113  	s *terraform.ResourceState,
   114  	meta interface{}) error {
   115  	p := meta.(*ResourceProvider)
   116  	conn := p.route53
   117  
   118  	// Get the record
   119  	rec, err := resource_aws_r53_build_record_set(s)
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	// Create the new records
   125  	req := &route53.ChangeResourceRecordSetsRequest{
   126  		Comment: "Deleted by Terraform",
   127  		Changes: []route53.Change{
   128  			route53.Change{
   129  				Action: "DELETE",
   130  				Record: *rec,
   131  			},
   132  		},
   133  	}
   134  	zone := s.Attributes["zone_id"]
   135  	log.Printf("[DEBUG] Deleting resource records for zone: %s, name: %s",
   136  		zone, s.Attributes["name"])
   137  	_, err = conn.ChangeResourceRecordSets(zone, req)
   138  	if err != nil {
   139  		return err
   140  	}
   141  	return nil
   142  }
   143  
   144  func resource_aws_r53_record_refresh(
   145  	s *terraform.ResourceState,
   146  	meta interface{}) (*terraform.ResourceState, error) {
   147  	p := meta.(*ResourceProvider)
   148  	conn := p.route53
   149  
   150  	zone := s.Attributes["zone_id"]
   151  	lopts := &route53.ListOpts{
   152  		Name: s.Attributes["name"],
   153  		Type: s.Attributes["type"],
   154  	}
   155  	resp, err := conn.ListResourceRecordSets(zone, lopts)
   156  	if err != nil {
   157  		return s, err
   158  	}
   159  
   160  	// Scan for a matching record
   161  	found := false
   162  	for _, record := range resp.Records {
   163  		if route53.FQDN(record.Name) != route53.FQDN(lopts.Name) {
   164  			continue
   165  		}
   166  		if strings.ToUpper(record.Type) != strings.ToUpper(lopts.Type) {
   167  			continue
   168  		}
   169  
   170  		found = true
   171  		resource_aws_r53_record_update_state(s, &record)
   172  		break
   173  	}
   174  	if !found {
   175  		s.ID = ""
   176  	}
   177  	return s, nil
   178  }
   179  
   180  func resource_aws_r53_record_update_state(
   181  	s *terraform.ResourceState,
   182  	rec *route53.ResourceRecordSet) {
   183  
   184  	flatRec := flatmap.Flatten(map[string]interface{}{
   185  		"records": rec.Records,
   186  	})
   187  	for k, v := range flatRec {
   188  		s.Attributes[k] = v
   189  	}
   190  
   191  	s.Attributes["ttl"] = strconv.FormatInt(int64(rec.TTL), 10)
   192  }
   193  
   194  func resource_aws_r53_record_diff(
   195  	s *terraform.ResourceState,
   196  	c *terraform.ResourceConfig,
   197  	meta interface{}) (*terraform.ResourceDiff, error) {
   198  	b := &diff.ResourceBuilder{
   199  		Attrs: map[string]diff.AttrType{
   200  			"zone_id": diff.AttrTypeCreate,
   201  			"name":    diff.AttrTypeCreate,
   202  			"type":    diff.AttrTypeCreate,
   203  			"ttl":     diff.AttrTypeUpdate,
   204  			"records": diff.AttrTypeUpdate,
   205  		},
   206  	}
   207  	return b.Diff(s, c)
   208  }