github.com/daveadams/terraform@v0.6.4-0.20160830094355-13ce74975936/builtin/providers/azurerm/resource_arm_traffic_manager_profile.go (about) 1 package azurerm 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "net/http" 8 "strings" 9 10 "github.com/Azure/azure-sdk-for-go/arm/trafficmanager" 11 "github.com/hashicorp/terraform/helper/hashcode" 12 "github.com/hashicorp/terraform/helper/schema" 13 ) 14 15 func resourceArmTrafficManagerProfile() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceArmTrafficManagerProfileCreate, 18 Read: resourceArmTrafficManagerProfileRead, 19 Update: resourceArmTrafficManagerProfileCreate, 20 Delete: resourceArmTrafficManagerProfileDelete, 21 Importer: &schema.ResourceImporter{ 22 State: schema.ImportStatePassthrough, 23 }, 24 25 Schema: map[string]*schema.Schema{ 26 "name": { 27 Type: schema.TypeString, 28 Required: true, 29 ForceNew: true, 30 }, 31 32 "profile_status": { 33 Type: schema.TypeString, 34 Optional: true, 35 Computed: true, 36 ValidateFunc: validateAzureRMTrafficManagerStatus, 37 }, 38 39 "traffic_routing_method": { 40 Type: schema.TypeString, 41 Required: true, 42 ValidateFunc: validateAzureRMTrafficManagerRoutingMethod, 43 }, 44 45 "dns_config": { 46 Type: schema.TypeSet, 47 Required: true, 48 Elem: &schema.Resource{ 49 Schema: map[string]*schema.Schema{ 50 "relative_name": { 51 Type: schema.TypeString, 52 ForceNew: true, 53 Required: true, 54 }, 55 "ttl": { 56 Type: schema.TypeInt, 57 Required: true, 58 ValidateFunc: validateAzureRMTrafficManagerTTL, 59 }, 60 }, 61 }, 62 Set: resourceAzureRMTrafficManagerDNSConfigHash, 63 }, 64 65 // inlined from dns_config for ease of use 66 "fqdn": { 67 Type: schema.TypeString, 68 Computed: true, 69 }, 70 71 "monitor_config": { 72 Type: schema.TypeSet, 73 Required: true, 74 Elem: &schema.Resource{ 75 Schema: map[string]*schema.Schema{ 76 "protocol": { 77 Type: schema.TypeString, 78 Required: true, 79 ValidateFunc: validateAzureRMTrafficManagerMonitorProtocol, 80 }, 81 "port": { 82 Type: schema.TypeInt, 83 Required: true, 84 ValidateFunc: validateAzureRMTrafficManagerMonitorPort, 85 }, 86 "path": { 87 Type: schema.TypeString, 88 Required: true, 89 }, 90 }, 91 }, 92 Set: resourceAzureRMTrafficManagerMonitorConfigHash, 93 }, 94 95 "resource_group_name": { 96 Type: schema.TypeString, 97 Required: true, 98 ForceNew: true, 99 }, 100 101 "tags": tagsSchema(), 102 }, 103 } 104 } 105 106 func resourceArmTrafficManagerProfileCreate(d *schema.ResourceData, meta interface{}) error { 107 client := meta.(*ArmClient).trafficManagerProfilesClient 108 109 log.Printf("[INFO] preparing arguments for Azure ARM virtual network creation.") 110 111 name := d.Get("name").(string) 112 // must be provided in request 113 location := "global" 114 resGroup := d.Get("resource_group_name").(string) 115 tags := d.Get("tags").(map[string]interface{}) 116 117 profile := trafficmanager.Profile{ 118 Name: &name, 119 Location: &location, 120 Properties: getArmTrafficManagerProfileProperties(d), 121 Tags: expandTags(tags), 122 } 123 124 _, err := client.CreateOrUpdate(resGroup, name, profile) 125 if err != nil { 126 return err 127 } 128 129 read, err := client.Get(resGroup, name) 130 if err != nil { 131 return err 132 } 133 if read.ID == nil { 134 return fmt.Errorf("Cannot read TrafficManager profile %s (resource group %s) ID", name, resGroup) 135 } 136 137 d.SetId(*read.ID) 138 139 return resourceArmTrafficManagerProfileRead(d, meta) 140 } 141 142 func resourceArmTrafficManagerProfileRead(d *schema.ResourceData, meta interface{}) error { 143 client := meta.(*ArmClient).trafficManagerProfilesClient 144 145 id, err := parseAzureResourceID(d.Id()) 146 if err != nil { 147 return err 148 } 149 resGroup := id.ResourceGroup 150 name := id.Path["trafficManagerProfiles"] 151 152 resp, err := client.Get(resGroup, name) 153 if resp.StatusCode == http.StatusNotFound { 154 d.SetId("") 155 return nil 156 } 157 if err != nil { 158 return fmt.Errorf("Error making Read request on Traffic Manager Profile %s: %s", name, err) 159 } 160 profile := *resp.Properties 161 162 // update appropriate values 163 d.Set("name", resp.Name) 164 d.Set("profile_status", profile.ProfileStatus) 165 d.Set("traffic_routing_method", profile.TrafficRoutingMethod) 166 167 dnsFlat := flattenAzureRMTrafficManagerProfileDNSConfig(profile.DNSConfig) 168 d.Set("dns_config", schema.NewSet(resourceAzureRMTrafficManagerDNSConfigHash, dnsFlat)) 169 170 // fqdn is actually inside DNSConfig, inlined for simpler reference 171 d.Set("fqdn", profile.DNSConfig.Fqdn) 172 173 monitorFlat := flattenAzureRMTrafficManagerProfileMonitorConfig(profile.MonitorConfig) 174 d.Set("monitor_config", schema.NewSet(resourceAzureRMTrafficManagerMonitorConfigHash, monitorFlat)) 175 176 flattenAndSetTags(d, resp.Tags) 177 178 return nil 179 } 180 181 func resourceArmTrafficManagerProfileDelete(d *schema.ResourceData, meta interface{}) error { 182 client := meta.(*ArmClient).trafficManagerProfilesClient 183 184 id, err := parseAzureResourceID(d.Id()) 185 if err != nil { 186 return err 187 } 188 resGroup := id.ResourceGroup 189 name := id.Path["trafficManagerProfiles"] 190 191 _, err = client.Delete(resGroup, name) 192 193 return err 194 } 195 196 func getArmTrafficManagerProfileProperties(d *schema.ResourceData) *trafficmanager.ProfileProperties { 197 routingMethod := d.Get("traffic_routing_method").(string) 198 props := &trafficmanager.ProfileProperties{ 199 TrafficRoutingMethod: &routingMethod, 200 DNSConfig: expandArmTrafficManagerDNSConfig(d), 201 MonitorConfig: expandArmTrafficManagerMonitorConfig(d), 202 } 203 204 if status, ok := d.GetOk("profile_status"); ok { 205 s := status.(string) 206 props.ProfileStatus = &s 207 } 208 209 return props 210 } 211 212 func expandArmTrafficManagerMonitorConfig(d *schema.ResourceData) *trafficmanager.MonitorConfig { 213 monitorSets := d.Get("monitor_config").(*schema.Set).List() 214 monitor := monitorSets[0].(map[string]interface{}) 215 216 proto := monitor["protocol"].(string) 217 port := int64(monitor["port"].(int)) 218 path := monitor["path"].(string) 219 220 return &trafficmanager.MonitorConfig{ 221 Protocol: &proto, 222 Port: &port, 223 Path: &path, 224 } 225 } 226 227 func expandArmTrafficManagerDNSConfig(d *schema.ResourceData) *trafficmanager.DNSConfig { 228 dnsSets := d.Get("dns_config").(*schema.Set).List() 229 dns := dnsSets[0].(map[string]interface{}) 230 231 name := dns["relative_name"].(string) 232 ttl := int64(dns["ttl"].(int)) 233 234 return &trafficmanager.DNSConfig{ 235 RelativeName: &name, 236 TTL: &ttl, 237 } 238 } 239 240 func flattenAzureRMTrafficManagerProfileDNSConfig(dns *trafficmanager.DNSConfig) []interface{} { 241 result := make(map[string]interface{}) 242 243 result["relative_name"] = *dns.RelativeName 244 result["ttl"] = int(*dns.TTL) 245 246 return []interface{}{result} 247 } 248 249 func flattenAzureRMTrafficManagerProfileMonitorConfig(cfg *trafficmanager.MonitorConfig) []interface{} { 250 result := make(map[string]interface{}) 251 252 result["protocol"] = *cfg.Protocol 253 result["port"] = int(*cfg.Port) 254 result["path"] = *cfg.Path 255 256 return []interface{}{result} 257 } 258 259 func resourceAzureRMTrafficManagerDNSConfigHash(v interface{}) int { 260 var buf bytes.Buffer 261 m := v.(map[string]interface{}) 262 263 buf.WriteString(fmt.Sprintf("%s-", m["relative_name"].(string))) 264 buf.WriteString(fmt.Sprintf("%d-", m["ttl"].(int))) 265 266 return hashcode.String(buf.String()) 267 } 268 269 func resourceAzureRMTrafficManagerMonitorConfigHash(v interface{}) int { 270 var buf bytes.Buffer 271 m := v.(map[string]interface{}) 272 273 buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["protocol"].(string)))) 274 buf.WriteString(fmt.Sprintf("%d-", m["port"].(int))) 275 buf.WriteString(fmt.Sprintf("%s-", m["path"].(string))) 276 277 return hashcode.String(buf.String()) 278 } 279 280 func validateAzureRMTrafficManagerStatus(i interface{}, k string) (s []string, errors []error) { 281 status := strings.ToLower(i.(string)) 282 if status != "enabled" && status != "disabled" { 283 errors = append(errors, fmt.Errorf("%s must be one of: Enabled, Disabled", k)) 284 } 285 return 286 } 287 288 func validateAzureRMTrafficManagerRoutingMethod(i interface{}, k string) (s []string, errors []error) { 289 valid := map[string]struct{}{ 290 "Performance": struct{}{}, 291 "Weighted": struct{}{}, 292 "Priority": struct{}{}, 293 } 294 295 if _, ok := valid[i.(string)]; !ok { 296 errors = append(errors, fmt.Errorf("traffic_routing_method must be one of (Performance, Weighted, Priority), got %s", i.(string))) 297 } 298 return 299 } 300 301 func validateAzureRMTrafficManagerTTL(i interface{}, k string) (s []string, errors []error) { 302 ttl := i.(int) 303 if ttl < 30 || ttl > 999999 { 304 errors = append(errors, fmt.Errorf("ttl must be between 30 and 999,999 inclusive")) 305 } 306 return 307 } 308 309 func validateAzureRMTrafficManagerMonitorProtocol(i interface{}, k string) (s []string, errors []error) { 310 p := i.(string) 311 if p != "http" && p != "https" { 312 errors = append(errors, fmt.Errorf("monitor_config.protocol must be one of: http, https")) 313 } 314 return 315 } 316 317 func validateAzureRMTrafficManagerMonitorPort(i interface{}, k string) (s []string, errors []error) { 318 p := i.(int) 319 if p < 1 || p > 65535 { 320 errors = append(errors, fmt.Errorf("monitor_config.port must be between 1 - 65535 inclusive")) 321 } 322 return 323 }