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 }