github.com/paulmey/terraform@v0.5.2-0.20150519145237-046e9b4c884d/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 "vpc_id": &schema.Schema{ 32 Type: schema.TypeString, 33 Optional: true, 34 ForceNew: true, 35 }, 36 37 "vpc_region": &schema.Schema{ 38 Type: schema.TypeString, 39 Optional: true, 40 ForceNew: true, 41 Computed: true, 42 }, 43 44 "zone_id": &schema.Schema{ 45 Type: schema.TypeString, 46 Computed: true, 47 }, 48 49 "name_servers": &schema.Schema{ 50 Type: schema.TypeList, 51 Elem: &schema.Schema{Type: schema.TypeString}, 52 Computed: true, 53 }, 54 55 "tags": tagsSchema(), 56 }, 57 } 58 } 59 60 func resourceAwsRoute53ZoneCreate(d *schema.ResourceData, meta interface{}) error { 61 r53 := meta.(*AWSClient).r53conn 62 63 comment := &route53.HostedZoneConfig{Comment: aws.String("Managed by Terraform")} 64 req := &route53.CreateHostedZoneInput{ 65 Name: aws.String(d.Get("name").(string)), 66 HostedZoneConfig: comment, 67 CallerReference: aws.String(time.Now().Format(time.RFC3339Nano)), 68 } 69 if v := d.Get("vpc_id"); v != "" { 70 req.VPC = &route53.VPC{ 71 VPCID: aws.String(v.(string)), 72 VPCRegion: aws.String(meta.(*AWSClient).region), 73 } 74 if w := d.Get("vpc_region"); w != "" { 75 req.VPC.VPCRegion = aws.String(w.(string)) 76 } 77 d.Set("vpc_region", req.VPC.VPCRegion) 78 } 79 80 log.Printf("[DEBUG] Creating Route53 hosted zone: %s", *req.Name) 81 resp, err := r53.CreateHostedZone(req) 82 if err != nil { 83 return err 84 } 85 86 // Store the zone_id 87 zone := cleanZoneID(*resp.HostedZone.ID) 88 d.Set("zone_id", zone) 89 d.SetId(zone) 90 91 // Wait until we are done initializing 92 wait := resource.StateChangeConf{ 93 Delay: 30 * time.Second, 94 Pending: []string{"PENDING"}, 95 Target: "INSYNC", 96 Timeout: 10 * time.Minute, 97 MinTimeout: 2 * time.Second, 98 Refresh: func() (result interface{}, state string, err error) { 99 changeRequest := &route53.GetChangeInput{ 100 ID: aws.String(cleanChangeID(*resp.ChangeInfo.ID)), 101 } 102 return resourceAwsGoRoute53Wait(r53, changeRequest) 103 }, 104 } 105 _, err = wait.WaitForState() 106 if err != nil { 107 return err 108 } 109 return resourceAwsRoute53ZoneUpdate(d, meta) 110 } 111 112 func resourceAwsRoute53ZoneRead(d *schema.ResourceData, meta interface{}) error { 113 r53 := meta.(*AWSClient).r53conn 114 zone, err := r53.GetHostedZone(&route53.GetHostedZoneInput{ID: aws.String(d.Id())}) 115 if err != nil { 116 // Handle a deleted zone 117 if r53err, ok := err.(aws.APIError); ok && r53err.Code == "NoSuchHostedZone" { 118 d.SetId("") 119 return nil 120 } 121 return err 122 } 123 124 if !*zone.HostedZone.Config.PrivateZone { 125 ns := make([]string, len(zone.DelegationSet.NameServers)) 126 for i := range zone.DelegationSet.NameServers { 127 ns[i] = *zone.DelegationSet.NameServers[i] 128 } 129 sort.Strings(ns) 130 if err := d.Set("name_servers", ns); err != nil { 131 return fmt.Errorf("[DEBUG] Error setting name servers for: %s, error: %#v", d.Id(), err) 132 } 133 } else { 134 ns, err := getNameServers(d.Id(), d.Get("name").(string), r53) 135 if err != nil { 136 return err 137 } 138 if err := d.Set("name_servers", ns); err != nil { 139 return fmt.Errorf("[DEBUG] Error setting name servers for: %s, error: %#v", d.Id(), err) 140 } 141 142 var associatedVPC *route53.VPC 143 for _, vpc := range zone.VPCs { 144 if *vpc.VPCID == d.Get("vpc_id") { 145 associatedVPC = vpc 146 } 147 } 148 if associatedVPC == nil { 149 return fmt.Errorf("[DEBUG] VPC: %v is not associated with Zone: %v", d.Get("vpc_id"), d.Id()) 150 } 151 } 152 153 // get tags 154 req := &route53.ListTagsForResourceInput{ 155 ResourceID: aws.String(d.Id()), 156 ResourceType: aws.String("hostedzone"), 157 } 158 159 resp, err := r53.ListTagsForResource(req) 160 if err != nil { 161 return err 162 } 163 164 var tags []*route53.Tag 165 if resp.ResourceTagSet != nil { 166 tags = resp.ResourceTagSet.Tags 167 } 168 169 if err := d.Set("tags", tagsToMapR53(tags)); err != nil { 170 return err 171 } 172 173 return nil 174 } 175 176 func resourceAwsRoute53ZoneUpdate(d *schema.ResourceData, meta interface{}) error { 177 conn := meta.(*AWSClient).r53conn 178 179 if err := setTagsR53(conn, d); err != nil { 180 return err 181 } else { 182 d.SetPartial("tags") 183 } 184 185 return resourceAwsRoute53ZoneRead(d, meta) 186 } 187 188 func resourceAwsRoute53ZoneDelete(d *schema.ResourceData, meta interface{}) error { 189 r53 := meta.(*AWSClient).r53conn 190 191 log.Printf("[DEBUG] Deleting Route53 hosted zone: %s (ID: %s)", 192 d.Get("name").(string), d.Id()) 193 _, err := r53.DeleteHostedZone(&route53.DeleteHostedZoneInput{ID: aws.String(d.Id())}) 194 if err != nil { 195 return err 196 } 197 198 return nil 199 } 200 201 func resourceAwsGoRoute53Wait(r53 *route53.Route53, ref *route53.GetChangeInput) (result interface{}, state string, err error) { 202 203 status, err := r53.GetChange(ref) 204 if err != nil { 205 return nil, "UNKNOWN", err 206 } 207 return true, *status.ChangeInfo.Status, nil 208 } 209 210 // cleanChangeID is used to remove the leading /change/ 211 func cleanChangeID(ID string) string { 212 return cleanPrefix(ID, "/change/") 213 } 214 215 // cleanZoneID is used to remove the leading /hostedzone/ 216 func cleanZoneID(ID string) string { 217 return cleanPrefix(ID, "/hostedzone/") 218 } 219 220 // cleanPrefix removes a string prefix from an ID 221 func cleanPrefix(ID, prefix string) string { 222 if strings.HasPrefix(ID, prefix) { 223 ID = strings.TrimPrefix(ID, prefix) 224 } 225 return ID 226 } 227 228 func getNameServers(zoneId string, zoneName string, r53 *route53.Route53) ([]string, error) { 229 resp, err := r53.ListResourceRecordSets(&route53.ListResourceRecordSetsInput{ 230 HostedZoneID: aws.String(zoneId), 231 StartRecordName: aws.String(zoneName), 232 StartRecordType: aws.String("NS"), 233 }) 234 if err != nil { 235 return nil, err 236 } 237 if len(resp.ResourceRecordSets) == 0 { 238 return nil, nil 239 } 240 ns := make([]string, len(resp.ResourceRecordSets[0].ResourceRecords)) 241 for i := range resp.ResourceRecordSets[0].ResourceRecords { 242 ns[i] = *resp.ResourceRecordSets[0].ResourceRecords[i].Value 243 } 244 sort.Strings(ns) 245 return ns, nil 246 }