github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/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 _, err := loadBalancerClient.CreateOrUpdate(resGroup, name, loadbalancer, make(chan struct{})) 131 if err != nil { 132 return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err) 133 } 134 135 read, err := loadBalancerClient.Get(resGroup, name, "") 136 if err != nil { 137 return errwrap.Wrapf("Error Getting LoadBalancer {{err}", err) 138 } 139 if read.ID == nil { 140 return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", name, resGroup) 141 } 142 143 d.SetId(*read.ID) 144 145 log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", name) 146 stateConf := &resource.StateChangeConf{ 147 Pending: []string{"Accepted", "Updating"}, 148 Target: []string{"Succeeded"}, 149 Refresh: loadbalancerStateRefreshFunc(client, resGroup, name), 150 Timeout: 10 * time.Minute, 151 } 152 if _, err := stateConf.WaitForState(); err != nil { 153 return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", name, err) 154 } 155 156 return resourecArmLoadBalancerRead(d, meta) 157 } 158 159 func resourecArmLoadBalancerRead(d *schema.ResourceData, meta interface{}) error { 160 id, err := parseAzureResourceID(d.Id()) 161 if err != nil { 162 return err 163 } 164 165 loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta) 166 if err != nil { 167 return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err) 168 } 169 if !exists { 170 d.SetId("") 171 log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string)) 172 return nil 173 } 174 175 d.Set("name", loadBalancer.Name) 176 d.Set("location", loadBalancer.Location) 177 d.Set("resource_group_name", id.ResourceGroup) 178 179 if loadBalancer.LoadBalancerPropertiesFormat != nil && loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations != nil { 180 ipconfigs := loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations 181 d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(ipconfigs)) 182 183 for _, config := range *ipconfigs { 184 if config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress != nil { 185 d.Set("private_ip_address", config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress) 186 187 // set the private IP address at most once 188 break 189 } 190 } 191 } 192 193 flattenAndSetTags(d, loadBalancer.Tags) 194 195 return nil 196 } 197 198 func resourceArmLoadBalancerDelete(d *schema.ResourceData, meta interface{}) error { 199 loadBalancerClient := meta.(*ArmClient).loadBalancerClient 200 201 id, err := parseAzureResourceID(d.Id()) 202 if err != nil { 203 return errwrap.Wrapf("Error Parsing Azure Resource ID {{err}}", err) 204 } 205 resGroup := id.ResourceGroup 206 name := id.Path["loadBalancers"] 207 208 _, err = loadBalancerClient.Delete(resGroup, name, make(chan struct{})) 209 if err != nil { 210 return errwrap.Wrapf("Error Deleting LoadBalancer {{err}}", err) 211 } 212 213 d.SetId("") 214 return nil 215 } 216 217 func expandAzureRmLoadBalancerFrontendIpConfigurations(d *schema.ResourceData) *[]network.FrontendIPConfiguration { 218 configs := d.Get("frontend_ip_configuration").([]interface{}) 219 frontEndConfigs := make([]network.FrontendIPConfiguration, 0, len(configs)) 220 221 for _, configRaw := range configs { 222 data := configRaw.(map[string]interface{}) 223 224 private_ip_allocation_method := data["private_ip_address_allocation"].(string) 225 properties := network.FrontendIPConfigurationPropertiesFormat{ 226 PrivateIPAllocationMethod: network.IPAllocationMethod(private_ip_allocation_method), 227 } 228 229 if v := data["private_ip_address"].(string); v != "" { 230 properties.PrivateIPAddress = &v 231 } 232 233 if v := data["public_ip_address_id"].(string); v != "" { 234 properties.PublicIPAddress = &network.PublicIPAddress{ 235 ID: &v, 236 } 237 } 238 239 if v := data["subnet_id"].(string); v != "" { 240 properties.Subnet = &network.Subnet{ 241 ID: &v, 242 } 243 } 244 245 name := data["name"].(string) 246 frontEndConfig := network.FrontendIPConfiguration{ 247 Name: &name, 248 FrontendIPConfigurationPropertiesFormat: &properties, 249 } 250 251 frontEndConfigs = append(frontEndConfigs, frontEndConfig) 252 } 253 254 return &frontEndConfigs 255 } 256 257 func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPConfiguration) []interface{} { 258 result := make([]interface{}, 0, len(*ipConfigs)) 259 for _, config := range *ipConfigs { 260 ipConfig := make(map[string]interface{}) 261 ipConfig["name"] = *config.Name 262 ipConfig["private_ip_address_allocation"] = config.FrontendIPConfigurationPropertiesFormat.PrivateIPAllocationMethod 263 264 if config.FrontendIPConfigurationPropertiesFormat.Subnet != nil { 265 ipConfig["subnet_id"] = *config.FrontendIPConfigurationPropertiesFormat.Subnet.ID 266 } 267 268 if config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress != nil { 269 ipConfig["private_ip_address"] = *config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress 270 } 271 272 if config.FrontendIPConfigurationPropertiesFormat.PublicIPAddress != nil { 273 ipConfig["public_ip_address_id"] = *config.FrontendIPConfigurationPropertiesFormat.PublicIPAddress.ID 274 } 275 276 if config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules != nil { 277 load_balancing_rules := make([]string, 0, len(*config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules)) 278 for _, rule := range *config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules { 279 load_balancing_rules = append(load_balancing_rules, *rule.ID) 280 } 281 282 ipConfig["load_balancer_rules"] = load_balancing_rules 283 284 } 285 286 if config.FrontendIPConfigurationPropertiesFormat.InboundNatRules != nil { 287 inbound_nat_rules := make([]string, 0, len(*config.FrontendIPConfigurationPropertiesFormat.InboundNatRules)) 288 for _, rule := range *config.FrontendIPConfigurationPropertiesFormat.InboundNatRules { 289 inbound_nat_rules = append(inbound_nat_rules, *rule.ID) 290 } 291 292 ipConfig["inbound_nat_rules"] = inbound_nat_rules 293 294 } 295 296 result = append(result, ipConfig) 297 } 298 return result 299 }