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