github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/azurerm/resource_arm_loadbalancer.go (about) 1 package azurerm 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/Azure/azure-sdk-for-go/arm/network" 9 "github.com/hashicorp/errwrap" 10 "github.com/hashicorp/terraform/helper/resource" 11 "github.com/hashicorp/terraform/helper/schema" 12 "github.com/jen20/riviera/azure" 13 ) 14 15 func resourceArmLoadBalancer() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceArmLoadBalancerCreate, 18 Read: resourecArmLoadBalancerRead, 19 Update: resourceArmLoadBalancerCreate, 20 Delete: resourceArmLoadBalancerDelete, 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 "location": locationSchema(), 33 34 "resource_group_name": { 35 Type: schema.TypeString, 36 Required: true, 37 ForceNew: true, 38 }, 39 40 "frontend_ip_configuration": { 41 Type: schema.TypeList, 42 Optional: true, 43 MinItems: 1, 44 Elem: &schema.Resource{ 45 Schema: map[string]*schema.Schema{ 46 "name": { 47 Type: schema.TypeString, 48 Required: true, 49 }, 50 51 "subnet_id": { 52 Type: schema.TypeString, 53 Optional: true, 54 Computed: true, 55 }, 56 57 "private_ip_address": { 58 Type: schema.TypeString, 59 Optional: true, 60 Computed: true, 61 }, 62 63 "public_ip_address_id": { 64 Type: schema.TypeString, 65 Optional: true, 66 Computed: true, 67 }, 68 69 "private_ip_address_allocation": { 70 Type: schema.TypeString, 71 Optional: true, 72 Computed: true, 73 ValidateFunc: validateLoadBalancerPrivateIpAddressAllocation, 74 StateFunc: ignoreCaseStateFunc, 75 DiffSuppressFunc: ignoreCaseDiffSuppressFunc, 76 }, 77 78 "load_balancer_rules": { 79 Type: schema.TypeSet, 80 Computed: true, 81 Elem: &schema.Schema{Type: schema.TypeString}, 82 Set: schema.HashString, 83 }, 84 85 "inbound_nat_rules": { 86 Type: schema.TypeSet, 87 Computed: true, 88 Elem: &schema.Schema{Type: schema.TypeString}, 89 Set: schema.HashString, 90 }, 91 }, 92 }, 93 }, 94 95 "private_ip_address": { 96 Type: schema.TypeString, 97 Computed: true, 98 }, 99 100 "tags": tagsSchema(), 101 }, 102 } 103 } 104 105 func resourceArmLoadBalancerCreate(d *schema.ResourceData, meta interface{}) error { 106 client := meta.(*ArmClient) 107 loadBalancerClient := client.loadBalancerClient 108 109 log.Printf("[INFO] preparing arguments for Azure ARM LoadBalancer creation.") 110 111 name := d.Get("name").(string) 112 location := d.Get("location").(string) 113 resGroup := d.Get("resource_group_name").(string) 114 tags := d.Get("tags").(map[string]interface{}) 115 expandedTags := expandTags(tags) 116 117 properties := network.LoadBalancerPropertiesFormat{} 118 119 if _, ok := d.GetOk("frontend_ip_configuration"); ok { 120 properties.FrontendIPConfigurations = expandAzureRmLoadBalancerFrontendIpConfigurations(d) 121 } 122 123 loadbalancer := network.LoadBalancer{ 124 Name: azure.String(name), 125 Location: azure.String(location), 126 Tags: expandedTags, 127 LoadBalancerPropertiesFormat: &properties, 128 } 129 130 _, error := loadBalancerClient.CreateOrUpdate(resGroup, name, loadbalancer, make(chan struct{})) 131 err := <-error 132 if err != nil { 133 return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err) 134 } 135 136 read, err := loadBalancerClient.Get(resGroup, name, "") 137 if err != nil { 138 return errwrap.Wrapf("Error Getting LoadBalancer {{err}", err) 139 } 140 if read.ID == nil { 141 return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", name, resGroup) 142 } 143 144 d.SetId(*read.ID) 145 146 log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", name) 147 stateConf := &resource.StateChangeConf{ 148 Pending: []string{"Accepted", "Updating"}, 149 Target: []string{"Succeeded"}, 150 Refresh: loadbalancerStateRefreshFunc(client, resGroup, name), 151 Timeout: 10 * time.Minute, 152 } 153 if _, err := stateConf.WaitForState(); err != nil { 154 return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", name, err) 155 } 156 157 return resourecArmLoadBalancerRead(d, meta) 158 } 159 160 func resourecArmLoadBalancerRead(d *schema.ResourceData, meta interface{}) error { 161 id, err := parseAzureResourceID(d.Id()) 162 if err != nil { 163 return err 164 } 165 166 loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta) 167 if err != nil { 168 return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err) 169 } 170 if !exists { 171 d.SetId("") 172 log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string)) 173 return nil 174 } 175 176 d.Set("name", loadBalancer.Name) 177 d.Set("location", loadBalancer.Location) 178 d.Set("resource_group_name", id.ResourceGroup) 179 180 if loadBalancer.LoadBalancerPropertiesFormat != nil && loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations != nil { 181 ipconfigs := loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations 182 d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(ipconfigs)) 183 184 for _, config := range *ipconfigs { 185 if config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress != nil { 186 d.Set("private_ip_address", config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress) 187 188 // set the private IP address at most once 189 break 190 } 191 } 192 } 193 194 flattenAndSetTags(d, loadBalancer.Tags) 195 196 return nil 197 } 198 199 func resourceArmLoadBalancerDelete(d *schema.ResourceData, meta interface{}) error { 200 loadBalancerClient := meta.(*ArmClient).loadBalancerClient 201 202 id, err := parseAzureResourceID(d.Id()) 203 if err != nil { 204 return errwrap.Wrapf("Error Parsing Azure Resource ID {{err}}", err) 205 } 206 resGroup := id.ResourceGroup 207 name := id.Path["loadBalancers"] 208 209 _, error := loadBalancerClient.Delete(resGroup, name, make(chan struct{})) 210 err = <-error 211 if err != nil { 212 return errwrap.Wrapf("Error Deleting LoadBalancer {{err}}", err) 213 } 214 215 d.SetId("") 216 return nil 217 } 218 219 func expandAzureRmLoadBalancerFrontendIpConfigurations(d *schema.ResourceData) *[]network.FrontendIPConfiguration { 220 configs := d.Get("frontend_ip_configuration").([]interface{}) 221 frontEndConfigs := make([]network.FrontendIPConfiguration, 0, len(configs)) 222 223 for _, configRaw := range configs { 224 data := configRaw.(map[string]interface{}) 225 226 private_ip_allocation_method := data["private_ip_address_allocation"].(string) 227 properties := network.FrontendIPConfigurationPropertiesFormat{ 228 PrivateIPAllocationMethod: network.IPAllocationMethod(private_ip_allocation_method), 229 } 230 231 if v := data["private_ip_address"].(string); v != "" { 232 properties.PrivateIPAddress = &v 233 } 234 235 if v := data["public_ip_address_id"].(string); v != "" { 236 properties.PublicIPAddress = &network.PublicIPAddress{ 237 ID: &v, 238 } 239 } 240 241 if v := data["subnet_id"].(string); v != "" { 242 properties.Subnet = &network.Subnet{ 243 ID: &v, 244 } 245 } 246 247 name := data["name"].(string) 248 frontEndConfig := network.FrontendIPConfiguration{ 249 Name: &name, 250 FrontendIPConfigurationPropertiesFormat: &properties, 251 } 252 253 frontEndConfigs = append(frontEndConfigs, frontEndConfig) 254 } 255 256 return &frontEndConfigs 257 } 258 259 func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPConfiguration) []interface{} { 260 result := make([]interface{}, 0, len(*ipConfigs)) 261 for _, config := range *ipConfigs { 262 ipConfig := make(map[string]interface{}) 263 ipConfig["name"] = *config.Name 264 ipConfig["private_ip_address_allocation"] = config.FrontendIPConfigurationPropertiesFormat.PrivateIPAllocationMethod 265 266 if config.FrontendIPConfigurationPropertiesFormat.Subnet != nil { 267 ipConfig["subnet_id"] = *config.FrontendIPConfigurationPropertiesFormat.Subnet.ID 268 } 269 270 if config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress != nil { 271 ipConfig["private_ip_address"] = *config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress 272 } 273 274 if config.FrontendIPConfigurationPropertiesFormat.PublicIPAddress != nil { 275 ipConfig["public_ip_address_id"] = *config.FrontendIPConfigurationPropertiesFormat.PublicIPAddress.ID 276 } 277 278 if config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules != nil { 279 load_balancing_rules := make([]string, 0, len(*config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules)) 280 for _, rule := range *config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules { 281 load_balancing_rules = append(load_balancing_rules, *rule.ID) 282 } 283 284 ipConfig["load_balancer_rules"] = load_balancing_rules 285 286 } 287 288 if config.FrontendIPConfigurationPropertiesFormat.InboundNatRules != nil { 289 inbound_nat_rules := make([]string, 0, len(*config.FrontendIPConfigurationPropertiesFormat.InboundNatRules)) 290 for _, rule := range *config.FrontendIPConfigurationPropertiesFormat.InboundNatRules { 291 inbound_nat_rules = append(inbound_nat_rules, *rule.ID) 292 } 293 294 ipConfig["inbound_nat_rules"] = inbound_nat_rules 295 296 } 297 298 result = append(result, ipConfig) 299 } 300 return result 301 }