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  }