github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 "tags": tagsSchema(), 96 }, 97 } 98 } 99 100 func resourceArmLoadBalancerCreate(d *schema.ResourceData, meta interface{}) error { 101 client := meta.(*ArmClient) 102 loadBalancerClient := client.loadBalancerClient 103 104 log.Printf("[INFO] preparing arguments for Azure ARM LoadBalancer creation.") 105 106 name := d.Get("name").(string) 107 location := d.Get("location").(string) 108 resGroup := d.Get("resource_group_name").(string) 109 tags := d.Get("tags").(map[string]interface{}) 110 expandedTags := expandTags(tags) 111 112 properties := network.LoadBalancerPropertiesFormat{} 113 114 if _, ok := d.GetOk("frontend_ip_configuration"); ok { 115 properties.FrontendIPConfigurations = expandAzureRmLoadBalancerFrontendIpConfigurations(d) 116 } 117 118 loadbalancer := network.LoadBalancer{ 119 Name: azure.String(name), 120 Location: azure.String(location), 121 Tags: expandedTags, 122 LoadBalancerPropertiesFormat: &properties, 123 } 124 125 _, err := loadBalancerClient.CreateOrUpdate(resGroup, name, loadbalancer, make(chan struct{})) 126 if err != nil { 127 return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err) 128 } 129 130 read, err := loadBalancerClient.Get(resGroup, name, "") 131 if err != nil { 132 return errwrap.Wrapf("Error Getting LoadBalancer {{err}", err) 133 } 134 if read.ID == nil { 135 return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", name, resGroup) 136 } 137 138 d.SetId(*read.ID) 139 140 log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", name) 141 stateConf := &resource.StateChangeConf{ 142 Pending: []string{"Accepted", "Updating"}, 143 Target: []string{"Succeeded"}, 144 Refresh: loadbalancerStateRefreshFunc(client, resGroup, name), 145 Timeout: 10 * time.Minute, 146 } 147 if _, err := stateConf.WaitForState(); err != nil { 148 return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", name, err) 149 } 150 151 return resourecArmLoadBalancerRead(d, meta) 152 } 153 154 func resourecArmLoadBalancerRead(d *schema.ResourceData, meta interface{}) error { 155 id, err := parseAzureResourceID(d.Id()) 156 if err != nil { 157 return err 158 } 159 160 loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta) 161 if err != nil { 162 return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err) 163 } 164 if !exists { 165 d.SetId("") 166 log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string)) 167 return nil 168 } 169 170 d.Set("name", loadBalancer.Name) 171 d.Set("location", loadBalancer.Location) 172 d.Set("resource_group_name", id.ResourceGroup) 173 174 if loadBalancer.LoadBalancerPropertiesFormat != nil && loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations != nil { 175 d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations)) 176 } 177 178 flattenAndSetTags(d, loadBalancer.Tags) 179 180 return nil 181 } 182 183 func resourceArmLoadBalancerDelete(d *schema.ResourceData, meta interface{}) error { 184 loadBalancerClient := meta.(*ArmClient).loadBalancerClient 185 186 id, err := parseAzureResourceID(d.Id()) 187 if err != nil { 188 return errwrap.Wrapf("Error Parsing Azure Resource ID {{err}}", err) 189 } 190 resGroup := id.ResourceGroup 191 name := id.Path["loadBalancers"] 192 193 _, err = loadBalancerClient.Delete(resGroup, name, make(chan struct{})) 194 if err != nil { 195 return errwrap.Wrapf("Error Deleting LoadBalancer {{err}}", err) 196 } 197 198 d.SetId("") 199 return nil 200 } 201 202 func expandAzureRmLoadBalancerFrontendIpConfigurations(d *schema.ResourceData) *[]network.FrontendIPConfiguration { 203 configs := d.Get("frontend_ip_configuration").([]interface{}) 204 frontEndConfigs := make([]network.FrontendIPConfiguration, 0, len(configs)) 205 206 for _, configRaw := range configs { 207 data := configRaw.(map[string]interface{}) 208 209 private_ip_allocation_method := data["private_ip_address_allocation"].(string) 210 properties := network.FrontendIPConfigurationPropertiesFormat{ 211 PrivateIPAllocationMethod: network.IPAllocationMethod(private_ip_allocation_method), 212 } 213 214 if v := data["private_ip_address"].(string); v != "" { 215 properties.PrivateIPAddress = &v 216 } 217 218 if v := data["public_ip_address_id"].(string); v != "" { 219 properties.PublicIPAddress = &network.PublicIPAddress{ 220 ID: &v, 221 } 222 } 223 224 if v := data["subnet_id"].(string); v != "" { 225 properties.Subnet = &network.Subnet{ 226 ID: &v, 227 } 228 } 229 230 name := data["name"].(string) 231 frontEndConfig := network.FrontendIPConfiguration{ 232 Name: &name, 233 FrontendIPConfigurationPropertiesFormat: &properties, 234 } 235 236 frontEndConfigs = append(frontEndConfigs, frontEndConfig) 237 } 238 239 return &frontEndConfigs 240 } 241 242 func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPConfiguration) []interface{} { 243 result := make([]interface{}, 0, len(*ipConfigs)) 244 for _, config := range *ipConfigs { 245 ipConfig := make(map[string]interface{}) 246 ipConfig["name"] = *config.Name 247 ipConfig["private_ip_address_allocation"] = config.FrontendIPConfigurationPropertiesFormat.PrivateIPAllocationMethod 248 249 if config.FrontendIPConfigurationPropertiesFormat.Subnet != nil { 250 ipConfig["subnet_id"] = *config.FrontendIPConfigurationPropertiesFormat.Subnet.ID 251 } 252 253 if config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress != nil { 254 ipConfig["private_ip_address"] = *config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress 255 } 256 257 if config.FrontendIPConfigurationPropertiesFormat.PublicIPAddress != nil { 258 ipConfig["public_ip_address_id"] = *config.FrontendIPConfigurationPropertiesFormat.PublicIPAddress.ID 259 } 260 261 if config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules != nil { 262 load_balancing_rules := make([]string, 0, len(*config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules)) 263 for _, rule := range *config.FrontendIPConfigurationPropertiesFormat.LoadBalancingRules { 264 load_balancing_rules = append(load_balancing_rules, *rule.ID) 265 } 266 267 ipConfig["load_balancer_rules"] = load_balancing_rules 268 269 } 270 271 if config.FrontendIPConfigurationPropertiesFormat.InboundNatRules != nil { 272 inbound_nat_rules := make([]string, 0, len(*config.FrontendIPConfigurationPropertiesFormat.InboundNatRules)) 273 for _, rule := range *config.FrontendIPConfigurationPropertiesFormat.InboundNatRules { 274 inbound_nat_rules = append(inbound_nat_rules, *rule.ID) 275 } 276 277 ipConfig["inbound_nat_rules"] = inbound_nat_rules 278 279 } 280 281 result = append(result, ipConfig) 282 } 283 return result 284 }