From 87060a2d88925c051aa6b7010ff33244f8a08e96 Mon Sep 17 00:00:00 2001 From: John Bresnahan Date: Fri, 29 Apr 2016 11:25:24 -1000 Subject: [PATCH 01/12] A simplifed load balancer resource for AzureRM This commit adds a resource for the ARM load balancer. The ARM LB is quite complicated and has many different configuration options. Instead of trying to implement them all in a potential confusing user experience this resources exposes the most common uses. With it a load balancer can be configured on a single public IP or subnet which can route to a single backend pool according to one load balancing rule and 1 probe. --- builtin/providers/azurerm/provider.go | 2 + .../azurerm/resource_arm_simple_lb.go | 501 ++++++++++++++++++ .../azurerm/resource_arm_simple_lb_test.go | 116 ++++ 3 files changed, 619 insertions(+) create mode 100644 builtin/providers/azurerm/resource_arm_simple_lb.go create mode 100644 builtin/providers/azurerm/resource_arm_simple_lb_test.go diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index 0dfdc07f7261..e48d5e05bed2 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -80,6 +80,8 @@ func Provider() terraform.ResourceProvider { "azurerm_sql_database": resourceArmSqlDatabase(), "azurerm_sql_firewall_rule": resourceArmSqlFirewallRule(), "azurerm_sql_server": resourceArmSqlServer(), + "azurerm_simple_lb": resourceArmSimpleLb(), +>>>>>>> A simplifed load balancer resource for AzureRM }, ConfigureFunc: providerConfigure, } diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go new file mode 100644 index 000000000000..3b17f8fe559c --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -0,0 +1,501 @@ +package azurerm + +import ( + "fmt" + "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/hashicorp/terraform/helper/schema" + "log" + "strings" +) + +// resourceArmLoadBalancer returns the *schema.Resource +// associated to load balancer resources on ARM. +func resourceArmSimpleLb() *schema.Resource { + return &schema.Resource{ + Create: resourceArmSimpleLbCreate, + Read: resourceArmSimpleLbRead, + Update: resourceArmSimpleLbUpdate, + Delete: resourceArmSimpleLbDelete, + + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "backend_pool_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "probe_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "frontend_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "location": &schema.Schema{ + Type: schema.TypeString, + Required: true, + StateFunc: azureRMNormalizeLocation, + }, + "frontend_private_ip_address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "frontend_allocation_method": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateAllocationMethod, + }, + "frontend_subnet": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "frontend_public_ip_address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "probe_protocol": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateProtocolType, + }, + "probe_port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "probe_interval": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "probe_number_of_probes": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "probe_request_path": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + + "rule_protocol": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateProtocolType, + }, + "rule_load_distribution": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateLoadDistribution, + }, + "rule_frontend_port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "rule_backend_port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + }, + } +} + +func validateAllocationMethod(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToLower(v.(string)) + allocations := map[string]bool{ + "static": true, + "dynamic": true, + } + + if !allocations[value] { + errors = append(errors, fmt.Errorf("Allocation method can only be Static or Dynamic")) + } + return +} + +func validateProtocolType(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToLower(v.(string)) + allocations := map[string]bool{ + "tcp": true, + "udp": true, + } + + if !allocations[value] { + errors = append(errors, fmt.Errorf("Protocol can only be tcp or udp")) + } + return +} + +func validateLoadDistribution(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToLower(v.(string)) + allocations := map[string]bool{ + "default": true, + "sourceip": true, + "sourceipprotocol": true, + } + + if !allocations[value] { + errors = append(errors, fmt.Errorf("Load Distribution can only be default, sourceIp, or sourceIpProtocol")) + } + return +} + +func pullOutLbRules(d *schema.ResourceData) (*[]network.LoadBalancingRule, error) { + log.Printf("[resourceArmSimpleLb] pullOutLbRules[enter]") + defer log.Printf("[resourceArmSimpleLb] pullOutLbRules[exit]") + + backendPoolId := d.Get("backend_pool_id").(string) + frontendIpId := d.Get("frontend_id").(string) + probeId := d.Get("probe_id").(string) + + backendPoolRef := network.SubResource{ID: &backendPoolId} + frontendIpRef := network.SubResource{ID: &frontendIpId} + probeRef := network.SubResource{ID: &probeId} + + returnRules := []network.LoadBalancingRule{} + + ruleName := fmt.Sprintf("%srule", d.Get("name").(string)) + ruleProtocol := network.TransportProtocol(d.Get("rule_protocol").(string)) + ruleFrontendPort := d.Get("rule_frontend_port").(int) + ruleBackendPort := d.Get("rule_backend_port").(int) + ruleLoadDistributionS := d.Get("rule_load_distribution").(string) + if ruleLoadDistributionS == "" { + ruleLoadDistributionS = "Default" + } + + rulesProps := network.LoadBalancingRulePropertiesFormat{ + FrontendIPConfiguration: &frontendIpRef, + BackendAddressPool: &backendPoolRef, + BackendPort: &ruleBackendPort, + FrontendPort: &ruleFrontendPort, + Protocol: ruleProtocol, + LoadDistribution: network.LoadDistribution(ruleLoadDistributionS), + Probe: &probeRef, + } + + ruleType := network.LoadBalancingRule{ + Name: &ruleName, + Properties: &rulesProps, + } + + returnRules = append(returnRules, ruleType) + + return &returnRules, nil +} + +func pullOutProbes(d *schema.ResourceData) (*[]network.Probe, error) { + log.Printf("[resourceArmSimpleLb] pullOutProbes[enter]") + defer log.Printf("[resourceArmSimpleLb] pullOutProbes[exit]") + + returnRules := []network.Probe{} + + probeName := fmt.Sprintf("%sprobe", d.Get("name").(string)) + + probeProtocol := network.ProbeProtocol(d.Get("probe_protocol").(string)) + probePort := d.Get("probe_port").(int) + probeInterval := d.Get("probe_interval").(int) + probeNumberOfProbes := d.Get("probe_number_of_probes").(int) + probeRequestPath := d.Get("probe_request_path").(string) + + probeProps := network.ProbePropertiesFormat{ + Protocol: probeProtocol, + Port: &probePort, + IntervalInSeconds: &probeInterval, + NumberOfProbes: &probeNumberOfProbes, + } + if probeRequestPath != "" { + probeProps.RequestPath = &probeRequestPath + } + probe := network.Probe{ + Name: &probeName, + Properties: &probeProps, + } + + returnRules = append(returnRules, probe) + return &returnRules, nil +} + +func pullOutFrontEndIps(d *schema.ResourceData) (*[]network.FrontendIPConfiguration, error) { + log.Printf("[resourceArmSimpleLb] pullOutFrontEndIps[enter]") + defer log.Printf("[resourceArmSimpleLb] pullOutFrontEndIps[exit]") + + returnRules := []network.FrontendIPConfiguration{} + + frontedIpName := fmt.Sprintf("%sfrontendip", d.Get("name").(string)) + frontedIpAllocationMethod := network.IPAllocationMethod(d.Get("frontend_allocation_method").(string)) + frontedIpSubnet := d.Get("frontend_subnet").(string) + frontedIpPublicIpAddress := d.Get("frontend_public_ip_address").(string) + frontedIpPrivateIpAddress := d.Get("frontend_private_ip_address").(string) + + if frontedIpSubnet == "" && frontedIpPublicIpAddress == "" { + var logMsg = fmt.Sprintf("[ERROR] Either a subnet of a public ip address must be provided") + log.Printf("[resourceArmSimpleLb] %s", logMsg) + return nil, fmt.Errorf(logMsg) + } + + if frontedIpPrivateIpAddress == "" && frontedIpAllocationMethod == network.Static { + var logMsg = fmt.Sprintf("An private IP address must be provided if static allocation is used.") + log.Printf("[resourceArmSimpleLb] %s", logMsg) + return nil, fmt.Errorf(logMsg) + } + + ipProps := network.FrontendIPConfigurationPropertiesFormat{ + PrivateIPAllocationMethod: frontedIpAllocationMethod} + + if frontedIpSubnet != "" { + subnet := network.Subnet{ID: &frontedIpSubnet} + ipProps.Subnet = &subnet + } + if frontedIpPublicIpAddress != "" { + pubIp := network.PublicIPAddress{ID: &frontedIpPublicIpAddress} + ipProps.PublicIPAddress = &pubIp + } + if frontedIpPrivateIpAddress != "" { + ipProps.PrivateIPAddress = &frontedIpPrivateIpAddress + } + + frontendIpConf := network.FrontendIPConfiguration{Name: &frontedIpName, Properties: &ipProps} + returnRules = append(returnRules, frontendIpConf) + return &returnRules, nil +} + +func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { + log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbCreate[enter]") + defer log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbCreate[exit]") + + lbClient := meta.(*ArmClient).loadBalancerClient + + // first; fetch a bunch of fields: + typ := d.Get("type").(string) + name := d.Get("name").(string) + location := d.Get("location").(string) + resGrp := d.Get("resource_group_name").(string) + + loadBalancer := network.LoadBalancer{ + Name: &name, + Type: &typ, + Location: &location, + Properties: &network.LoadBalancerPropertiesFormat{}, + } + + fipconfs, err := pullOutFrontEndIps(d) + if err != nil { + return err + } + loadBalancer.Properties.FrontendIPConfigurations = fipconfs + probes, err := pullOutProbes(d) + if err != nil { + return err + } + loadBalancer.Properties.Probes = probes + + new_backend_pool_name := fmt.Sprintf("%sbackendpool", name) + backendpool := network.BackendAddressPool{Name: &new_backend_pool_name} + backendPoolConfs := []network.BackendAddressPool{} + backendPoolConfs = append(backendPoolConfs, backendpool) + loadBalancer.Properties.BackendAddressPools = &backendPoolConfs + + resp, err := lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR LB got status %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) + } + log.Printf("[resourceArmSimpleLb] Create LB got status %d", resp.StatusCode) + + d.SetId(*resp.ID) + err = iResourceArmSimpleLbRead(d, meta) + if err != nil { + return err + } + + log.Printf("[resourceArmSimpleLb] We have the IDs now updating to set rules") + loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d) + if err != nil { + return err + } + resp, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR LB got status %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) + } + + return iResourceArmSimpleLbRead(d, meta) +} + +func flattenAzureRmFrontendIp(frontenIpArray []network.FrontendIPConfiguration, d *schema.ResourceData) error { + log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[enter]") + defer log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[exit]") + + if len(frontenIpArray) < 1 { + return nil + } + if len(frontenIpArray) > 1 { + log.Printf("[WARN] More than 1 frontend ip was found. The simpleLB resource will just use the first one.") + } + + frontenIp := frontenIpArray[0] + + if frontenIp.Properties.PrivateIPAddress != nil { + d.Set("frontend_private_ip_address", *frontenIp.Properties.PrivateIPAddress) + } + d.Set("frontend_allocation_method", string(frontenIp.Properties.PrivateIPAllocationMethod)) + if frontenIp.Properties.Subnet != nil { + d.Set("frontend_subnet", *frontenIp.Properties.Subnet.ID) + } + if frontenIp.Properties.PublicIPAddress != nil { + d.Set("frontend_public_ip_address", *frontenIp.Properties.PublicIPAddress.ID) + } + + return nil +} + +func flattenAzureRmLoadBalancerRules(loadBalancingRuleArray []network.LoadBalancingRule, d *schema.ResourceData) error { + log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[enter]") + defer log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[exit]") + + if len(loadBalancingRuleArray) < 1 { + return nil + } + if len(loadBalancingRuleArray) > 1 { + log.Printf("[WARN] More than 1 load balancing rule was found. The simpleLB resource will just use the first one.") + } + + loadBalancingRule := loadBalancingRuleArray[0] + d.Set("rule_protocol", string(loadBalancingRule.Properties.Protocol)) + d.Set("rule_load_distribution", string(loadBalancingRule.Properties.LoadDistribution)) + d.Set("rule_frontend_port", *loadBalancingRule.Properties.FrontendPort) + d.Set("rule_backend_port", *loadBalancingRule.Properties.BackendPort) + + return nil +} + +func flattenAzureRmProbe(probeArray []network.Probe, d *schema.ResourceData) error { + log.Printf("[resourceArmSimpleLb] flattenAzureRmProbe[enter]") + defer log.Printf("[resourceArmSimpleLb] flattenAzureRmProbe[exit]") + + if len(probeArray) < 1 { + return nil + } + if len(probeArray) > 1 { + log.Printf("[WARN] More than 1 load balancing rule was found. The simpleLB resource will just use the first one.") + } + + probe := probeArray[0] + + d.Set("probe_protocol", string(probe.Properties.Protocol)) + d.Set("probe_port", *probe.Properties.Port) + d.Set("probe_interval", *probe.Properties.IntervalInSeconds) + d.Set("probe_number_of_probes", *probe.Properties.NumberOfProbes) + if probe.Properties.RequestPath != nil { + d.Set("probe_request_path", *probe.Properties.RequestPath) + } + + return nil +} + +func resourceArmSimpleLbUpdate(d *schema.ResourceData, meta interface{}) error { + log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbUpdate[enter]") + defer log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbUpdate[exit]") + + return resourceArmSimpleLbCreate(d, meta) +} + +func resourceArmSimpleLbDelete(d *schema.ResourceData, meta interface{}) error { + log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbDelete[enter]") + defer log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbDelete[exit]") + + lbClient := meta.(*ArmClient).loadBalancerClient + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + + log.Printf("[INFO] Issuing deletion request to Azure ARM for load balancer '%s'.", name) + + resp, err := lbClient.Delete(resGroup, name) + if err != nil { + return fmt.Errorf("Error issuing Azure ARM delete request for load balancer '%s': %s", name, err) + } + + log.Printf("[resourceArmSimpleLb] delete response %d %s", resp.StatusCode, resp.Status) + + return nil +} + +// resourceArmLoadBalancerRead goes ahead and reads the state of the corresponding ARM load balancer. +func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { + log.Printf("[resourceArmSimpleLb] iResourceArmSimpleLbRead[enter]") + defer log.Printf("[resourceArmSimpleLb] iResourceArmSimpleLbRead[exit]") + + lbClient := meta.(*ArmClient).loadBalancerClient + + name := d.Get("name").(string) + resGrp := d.Get("resource_group_name").(string) + + log.Printf("[INFO] Issuing read request of load balancer '%s' off Azure.", name) + + loadBalancer, err := lbClient.Get(resGrp, name, "") + if err != nil { + return fmt.Errorf("Error reading the state of the load balancer off Azure: %s", err) + } + + log.Printf("[INFO] Succesfully retrieved details for load balancer '%s'.", *loadBalancer.Name) + + fip := loadBalancer.Properties.FrontendIPConfigurations + + d.Set("location", loadBalancer.Location) + d.Set("type", loadBalancer.Type) + + err = flattenAzureRmFrontendIp(*fip, d) + if err != nil { + return err + } + err = flattenAzureRmProbe(*loadBalancer.Properties.Probes, d) + if err != nil { + return err + } + if loadBalancer.Properties.BackendAddressPools == nil || len(*loadBalancer.Properties.BackendAddressPools) != 1 { + return fmt.Errorf("There must be exactly 1 backend pool to use this resource") + } + d.Set("backend_pool_id", (*loadBalancer.Properties.BackendAddressPools)[0].ID) + if loadBalancer.Properties.Probes == nil || len(*loadBalancer.Properties.Probes) != 1 { + return fmt.Errorf("There must be exactly 1 probe to use this resource") + } + d.Set("probe_id", (*loadBalancer.Properties.Probes)[0].ID) + if loadBalancer.Properties.FrontendIPConfigurations == nil || len(*loadBalancer.Properties.FrontendIPConfigurations) != 1 { + return fmt.Errorf("There must be exactly 1 probe to use this resource") + } + d.Set("frontend_id", (*loadBalancer.Properties.FrontendIPConfigurations)[0].ID) + err = flattenAzureRmLoadBalancerRules(*loadBalancer.Properties.LoadBalancingRules, d) + if err != nil { + return err + } + return nil +} + +// resourceArmLoadBalancerRead goes ahead and reads the state of the corresponding ARM load balancer. +func resourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { + log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbRead[enter]") + defer log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbRead[exit]") + + return iResourceArmSimpleLbRead(d, meta) +} diff --git a/builtin/providers/azurerm/resource_arm_simple_lb_test.go b/builtin/providers/azurerm/resource_arm_simple_lb_test.go new file mode 100644 index 000000000000..03592d002a19 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_simple_lb_test.go @@ -0,0 +1,116 @@ +package azurerm + +import ( + "fmt" + "net/http" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAzureSimpleLB_basic(t *testing.T) { + + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureSimpleLB_min, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureSimpleRMLBDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureSimpleLBExists("azurerm_simple_lb.test"), + ), + }, + }, + }) +} + +func testCheckAzureSimpleLBExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + name := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for cdn endpoint: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).loadBalancerClient + + resp, err := conn.Get(resourceGroup, name, "") + if err != nil { + return fmt.Errorf("Bad: Get on loadBalancerClient: %s", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Load Balancer %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} + +func testCheckAzureSimpleRMLBDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).loadBalancerClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_load_balancer" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(resourceGroup, name, "") + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Load balancer still exists:\n%#v", resp.Properties) + } + } + + return nil +} + +var testAccAzureSimpleLB_min = ` +resource "azurerm_resource_group" "test" { + name = "acctestlbrg-%d" + location = "West US" +} + +resource "azurerm_public_ip" "test" { + name = "simplelbip" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "static" +} + +resource "azurerm_simple_lb" "test" { + name = "acctestlb%d" + location = "West US" + type = "Microsoft.Network/loadBalancers" + resource_group_name = "${azurerm_resource_group.test.name}" + frontend_allocation_method = "Dynamic" + frontend_public_ip_address = "${azurerm_public_ip.test.id}" + probe_protocol = "Tcp" + probe_port = 22 + probe_interval = 5 + probe_number_of_probes = 16 + rule_protocol = "Tcp" + rule_load_distribution = "Default" + rule_frontend_port = 22 + rule_backend_port = 22 +} +` From f351ea09190d98ab2b1632f068c1eb9ca725a71a Mon Sep 17 00:00:00 2001 From: John Bresnahan Date: Mon, 9 May 2016 08:25:13 -1000 Subject: [PATCH 02/12] Multiple probes and balancing rules for the simple load balancer This patch extends the simple load balancer to allow users to have multiple rules and probes for a single frontend and single backend pool. --- .../azurerm/resource_arm_simple_lb.go | 378 ++++++++++++------ .../azurerm/resource_arm_simple_lb_test.go | 24 +- 2 files changed, 262 insertions(+), 140 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index 3b17f8fe559c..c3bcc8b76fd0 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" "log" "strings" @@ -28,11 +29,6 @@ func resourceArmSimpleLb() *schema.Resource { Computed: true, }, - "probe_id": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - "frontend_id": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -76,50 +72,106 @@ func resourceArmSimpleLb() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "probe_protocol": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ValidateFunc: validateProtocolType, - }, - "probe_port": &schema.Schema{ - Type: schema.TypeInt, - Required: true, - }, - "probe_interval": &schema.Schema{ - Type: schema.TypeInt, - Required: true, - }, - "probe_number_of_probes": &schema.Schema{ - Type: schema.TypeInt, - Required: true, - }, - "probe_request_path": &schema.Schema{ - Type: schema.TypeString, + + "probe": &schema.Schema{ + Type: schema.TypeSet, Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "protocol": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateProbeProtocolType, + }, + "request_path": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "interval": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "number_of_probes": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "probe_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + Set: resourceARMLoadBalancerProbeHash, }, - "rule_protocol": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ValidateFunc: validateProtocolType, - }, - "rule_load_distribution": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ValidateFunc: validateLoadDistribution, - }, - "rule_frontend_port": &schema.Schema{ - Type: schema.TypeInt, - Required: true, - }, - "rule_backend_port": &schema.Schema{ - Type: schema.TypeInt, - Required: true, + "rule": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "rule_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "protocol": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateProtocolType, + }, + "probe_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "load_distribution": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateLoadDistribution, + }, + "frontend_port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "backend_port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + }, + }, + Set: resourceARMLoadBalancerRuleHash, }, }, } } +func resourceARMLoadBalancerRuleHash(v interface{}) int { + m := v.(map[string]interface{}) + rule := fmt.Sprintf("%s-%s-%s%d-%d", m["name"].(string), m["protocol"].(string), m["load_distribution"].(string), m["frontend_port"], m["backend_port"]) + return hashcode.String(rule) +} + +func resourceARMLoadBalancerProbeHash(v interface{}) int { + m := v.(map[string]interface{}) + rule := fmt.Sprintf("%s-%s-%d-%d", m["name"].(string), m["protocol"].(string), m["frontend_port"], m["backend_port"]) + if m["request_path"] != nil { + rule = rule + "-" + m["request_path"].(string) + } + return hashcode.String(rule) +} + func validateAllocationMethod(v interface{}, k string) (ws []string, errors []error) { value := strings.ToLower(v.(string)) allocations := map[string]bool{ @@ -146,6 +198,19 @@ func validateProtocolType(v interface{}, k string) (ws []string, errors []error) return } +func validateProbeProtocolType(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToLower(v.(string)) + allocations := map[string]bool{ + "tcp": true, + "http": true, + } + + if !allocations[value] { + errors = append(errors, fmt.Errorf("Protocol can only be tcp or udp")) + } + return +} + func validateLoadDistribution(v interface{}, k string) (ws []string, errors []error) { value := strings.ToLower(v.(string)) allocations := map[string]bool{ @@ -160,79 +225,111 @@ func validateLoadDistribution(v interface{}, k string) (ws []string, errors []er return } -func pullOutLbRules(d *schema.ResourceData) (*[]network.LoadBalancingRule, error) { +func findProbeConfByName(probeArray *[]network.Probe, probeName string) (int, error) { + for i := 0; i < len(*probeArray); i++ { + tmpProbe := (*probeArray)[i] + if *tmpProbe.Name == probeName { + return i, nil + } + } + return -1, fmt.Errorf("Error loading the probe named %s", probeName) +} + +func findProbeConfById(probeArray *[]network.Probe, probeId string) (int, error) { + for i := 0; i < len(*probeArray); i++ { + tmpProbe := (*probeArray)[i] + if *tmpProbe.ID == probeId { + return i, nil + } + } + return -1, fmt.Errorf("Error finding the probe ID %s", probeId) +} + +func pullOutLbRules(d *schema.ResourceData, loadBalancer network.LoadBalancer) (*[]network.LoadBalancingRule, error) { log.Printf("[resourceArmSimpleLb] pullOutLbRules[enter]") defer log.Printf("[resourceArmSimpleLb] pullOutLbRules[exit]") backendPoolId := d.Get("backend_pool_id").(string) frontendIpId := d.Get("frontend_id").(string) - probeId := d.Get("probe_id").(string) - backendPoolRef := network.SubResource{ID: &backendPoolId} frontendIpRef := network.SubResource{ID: &frontendIpId} - probeRef := network.SubResource{ID: &probeId} - - returnRules := []network.LoadBalancingRule{} - - ruleName := fmt.Sprintf("%srule", d.Get("name").(string)) - ruleProtocol := network.TransportProtocol(d.Get("rule_protocol").(string)) - ruleFrontendPort := d.Get("rule_frontend_port").(int) - ruleBackendPort := d.Get("rule_backend_port").(int) - ruleLoadDistributionS := d.Get("rule_load_distribution").(string) - if ruleLoadDistributionS == "" { - ruleLoadDistributionS = "Default" - } - - rulesProps := network.LoadBalancingRulePropertiesFormat{ - FrontendIPConfiguration: &frontendIpRef, - BackendAddressPool: &backendPoolRef, - BackendPort: &ruleBackendPort, - FrontendPort: &ruleFrontendPort, - Protocol: ruleProtocol, - LoadDistribution: network.LoadDistribution(ruleLoadDistributionS), - Probe: &probeRef, - } - - ruleType := network.LoadBalancingRule{ - Name: &ruleName, - Properties: &rulesProps, - } - - returnRules = append(returnRules, ruleType) - return &returnRules, nil + // then; the subnets: + outRules := []network.LoadBalancingRule{} + if rules := d.Get("rule").(*schema.Set); rules.Len() > 0 { + for _, rule := range rules.List() { + rule := rule.(map[string]interface{}) + + ruleName := rule["name"].(string) + ruleProtocol := rule["protocol"].(string) + ruleProbeName := rule["probe_name"].(string) + loadDistribution := rule["load_distribution"].(string) + frontendPort := rule["frontend_port"].(int) + backendendPort := rule["backend_port"].(int) + + i, err := findProbeConfByName(loadBalancer.Properties.Probes, ruleProbeName) + if err != nil { + return nil, err + } + + probeRef := network.SubResource{ID: (*loadBalancer.Properties.Probes)[i].ID} + + props := network.LoadBalancingRulePropertiesFormat{ + Protocol: network.TransportProtocol(ruleProtocol), + LoadDistribution: network.LoadDistribution(loadDistribution), + FrontendPort: &frontendPort, + BackendPort: &backendendPort, + Probe: &probeRef, + BackendAddressPool: &backendPoolRef, + FrontendIPConfiguration: &frontendIpRef, + } + ruleObj := network.LoadBalancingRule{ + Name: &ruleName, + Properties: &props, + } + outRules = append(outRules, ruleObj) + } + } + + return &outRules, nil } func pullOutProbes(d *schema.ResourceData) (*[]network.Probe, error) { log.Printf("[resourceArmSimpleLb] pullOutProbes[enter]") defer log.Printf("[resourceArmSimpleLb] pullOutProbes[exit]") - returnRules := []network.Probe{} - - probeName := fmt.Sprintf("%sprobe", d.Get("name").(string)) - - probeProtocol := network.ProbeProtocol(d.Get("probe_protocol").(string)) - probePort := d.Get("probe_port").(int) - probeInterval := d.Get("probe_interval").(int) - probeNumberOfProbes := d.Get("probe_number_of_probes").(int) - probeRequestPath := d.Get("probe_request_path").(string) - - probeProps := network.ProbePropertiesFormat{ - Protocol: probeProtocol, - Port: &probePort, - IntervalInSeconds: &probeInterval, - NumberOfProbes: &probeNumberOfProbes, - } - if probeRequestPath != "" { - probeProps.RequestPath = &probeRequestPath - } - probe := network.Probe{ - Name: &probeName, - Properties: &probeProps, - } - - returnRules = append(returnRules, probe) - return &returnRules, nil + // then; the subnets: + outProbes := []network.Probe{} + if probes := d.Get("probe").(*schema.Set); probes.Len() > 0 { + for _, probe := range probes.List() { + probe := probe.(map[string]interface{}) + + probeName := probe["name"].(string) + ruleProtocol := probe["protocol"].(string) + requestPath := probe["request_path"].(string) + port := probe["port"].(int) + interval := probe["interval"].(int) + numberOfProbes := probe["number_of_probes"].(int) + + probeProps := network.ProbePropertiesFormat{ + Protocol: network.ProbeProtocol(ruleProtocol), + Port: &port, + IntervalInSeconds: &interval, + NumberOfProbes: &numberOfProbes, + } + if requestPath != "" { + probeProps.RequestPath = &requestPath + } + + probeObj := network.Probe{ + Name: &probeName, + Properties: &probeProps, + } + outProbes = append(outProbes, probeObj) + } + } + + return &outProbes, nil } func pullOutFrontEndIps(d *schema.ResourceData) (*[]network.FrontendIPConfiguration, error) { @@ -329,7 +426,7 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { } log.Printf("[resourceArmSimpleLb] We have the IDs now updating to set rules") - loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d) + loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d, resp) if err != nil { return err } @@ -369,46 +466,67 @@ func flattenAzureRmFrontendIp(frontenIpArray []network.FrontendIPConfiguration, return nil } -func flattenAzureRmLoadBalancerRules(loadBalancingRuleArray []network.LoadBalancingRule, d *schema.ResourceData) error { +func flattenAzureRmLoadBalancerRules(loadBalancer network.LoadBalancer, d *schema.ResourceData) error { log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[enter]") defer log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[exit]") - if len(loadBalancingRuleArray) < 1 { - return nil - } - if len(loadBalancingRuleArray) > 1 { - log.Printf("[WARN] More than 1 load balancing rule was found. The simpleLB resource will just use the first one.") + loadBalancingRuleArray := loadBalancer.Properties.LoadBalancingRules + + ruleSet := &schema.Set{ + F: resourceARMLoadBalancerProbeHash, } - loadBalancingRule := loadBalancingRuleArray[0] - d.Set("rule_protocol", string(loadBalancingRule.Properties.Protocol)) - d.Set("rule_load_distribution", string(loadBalancingRule.Properties.LoadDistribution)) - d.Set("rule_frontend_port", *loadBalancingRule.Properties.FrontendPort) - d.Set("rule_backend_port", *loadBalancingRule.Properties.BackendPort) + for _, rule := range *loadBalancingRuleArray { + r := map[string]interface{}{} + + r["name"] = *rule.Name + r["rule_id"] = *rule.ID + if rule.Properties != nil { + r["protocol"] = string(rule.Properties.Protocol) + r["load_distribution"] = string(rule.Properties.LoadDistribution) + r["frontend_port"] = *rule.Properties.FrontendPort + r["backend_port"] = *rule.Properties.BackendPort + + ruleProbeID := *rule.Properties.Probe.ID + i, err := findProbeConfById(loadBalancer.Properties.Probes, ruleProbeID) + if err != nil { + return err + } + r["probe_name"] = *(*loadBalancer.Properties.Probes)[i].Name + } + ruleSet.Add(r) + } + d.Set("subnet", ruleSet) return nil } -func flattenAzureRmProbe(probeArray []network.Probe, d *schema.ResourceData) error { +func flattenAzureRmProbe(probeArray *[]network.Probe, d *schema.ResourceData) error { log.Printf("[resourceArmSimpleLb] flattenAzureRmProbe[enter]") defer log.Printf("[resourceArmSimpleLb] flattenAzureRmProbe[exit]") - if len(probeArray) < 1 { - return nil - } - if len(probeArray) > 1 { - log.Printf("[WARN] More than 1 load balancing rule was found. The simpleLB resource will just use the first one.") + probeSet := &schema.Set{ + F: resourceARMLoadBalancerProbeHash, } - probe := probeArray[0] + for _, probe := range *probeArray { + p := map[string]interface{}{} - d.Set("probe_protocol", string(probe.Properties.Protocol)) - d.Set("probe_port", *probe.Properties.Port) - d.Set("probe_interval", *probe.Properties.IntervalInSeconds) - d.Set("probe_number_of_probes", *probe.Properties.NumberOfProbes) - if probe.Properties.RequestPath != nil { - d.Set("probe_request_path", *probe.Properties.RequestPath) + p["name"] = *probe.Name + p["probe_id"] = *probe.ID + if probe.Properties != nil { + p["protocol"] = string(probe.Properties.Protocol) + p["port"] = *probe.Properties.Port + p["interval"] = *probe.Properties.IntervalInSeconds + p["number_of_probes"] = *probe.Properties.NumberOfProbes + if probe.Properties.RequestPath != nil { + p["request_path"] = *probe.Properties.RequestPath + } + } + + probeSet.Add(p) } + d.Set("subnet", probeSet) return nil } @@ -469,7 +587,7 @@ func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } - err = flattenAzureRmProbe(*loadBalancer.Properties.Probes, d) + err = flattenAzureRmProbe(loadBalancer.Properties.Probes, d) if err != nil { return err } @@ -477,15 +595,11 @@ func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("There must be exactly 1 backend pool to use this resource") } d.Set("backend_pool_id", (*loadBalancer.Properties.BackendAddressPools)[0].ID) - if loadBalancer.Properties.Probes == nil || len(*loadBalancer.Properties.Probes) != 1 { - return fmt.Errorf("There must be exactly 1 probe to use this resource") - } - d.Set("probe_id", (*loadBalancer.Properties.Probes)[0].ID) if loadBalancer.Properties.FrontendIPConfigurations == nil || len(*loadBalancer.Properties.FrontendIPConfigurations) != 1 { - return fmt.Errorf("There must be exactly 1 probe to use this resource") + return fmt.Errorf("There must be exactly 1 fronted to use this resource") } d.Set("frontend_id", (*loadBalancer.Properties.FrontendIPConfigurations)[0].ID) - err = flattenAzureRmLoadBalancerRules(*loadBalancer.Properties.LoadBalancingRules, d) + err = flattenAzureRmLoadBalancerRules(loadBalancer, d) if err != nil { return err } diff --git a/builtin/providers/azurerm/resource_arm_simple_lb_test.go b/builtin/providers/azurerm/resource_arm_simple_lb_test.go index 03592d002a19..2cee952d1758 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb_test.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb_test.go @@ -104,13 +104,21 @@ resource "azurerm_simple_lb" "test" { resource_group_name = "${azurerm_resource_group.test.name}" frontend_allocation_method = "Dynamic" frontend_public_ip_address = "${azurerm_public_ip.test.id}" - probe_protocol = "Tcp" - probe_port = 22 - probe_interval = 5 - probe_number_of_probes = 16 - rule_protocol = "Tcp" - rule_load_distribution = "Default" - rule_frontend_port = 22 - rule_backend_port = 22 + + probe { + name = "testProbe1" + protocol = "Tcp" + port = 22 + interval = 5 + number_of_probes = 16 + } + rule { + protocol = "Tcp" + load_distribution = "Default" + frontend_port = 22 + backend_port = 22 + name = "rule1" + probe_name = "testProbe1" + } } ` From b8d1201a318c72175e2540a256959db4eb0c0ca2 Mon Sep 17 00:00:00 2001 From: John Bresnahan Date: Mon, 9 May 2016 10:55:11 -1000 Subject: [PATCH 03/12] Add tags and additional tests to the simple load balancer --- .../azurerm/resource_arm_simple_lb.go | 5 + .../azurerm/resource_arm_simple_lb_test.go | 145 +++++++++++++++++- 2 files changed, 143 insertions(+), 7 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index c3bcc8b76fd0..5eb625ff0426 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -153,6 +153,7 @@ func resourceArmSimpleLb() *schema.Resource { }, Set: resourceARMLoadBalancerRuleHash, }, + "tags": tagsSchema(), }, } } @@ -387,12 +388,14 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { name := d.Get("name").(string) location := d.Get("location").(string) resGrp := d.Get("resource_group_name").(string) + tags := d.Get("tags").(map[string]interface{}) loadBalancer := network.LoadBalancer{ Name: &name, Type: &typ, Location: &location, Properties: &network.LoadBalancerPropertiesFormat{}, + Tags: expandTags(tags), } fipconfs, err := pullOutFrontEndIps(d) @@ -603,6 +606,8 @@ func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } + flattenAndSetTags(d, loadBalancer.Tags) + return nil } diff --git a/builtin/providers/azurerm/resource_arm_simple_lb_test.go b/builtin/providers/azurerm/resource_arm_simple_lb_test.go index 2cee952d1758..2a17d88dc48a 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb_test.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb_test.go @@ -8,29 +8,72 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" + "regexp" ) -func TestAccAzureSimpleLB_basic(t *testing.T) { +func TestAccARMSimpleLB_basic(t *testing.T) { ri := acctest.RandInt() - config := fmt.Sprintf(testAccAzureSimpleLB_min, ri, ri) + config := fmt.Sprintf(testAccAzureSimpleLB_basic, ri, ri) + + justBeThere := regexp.MustCompile(".*") resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testCheckAzureSimpleRMLBDestroy, + CheckDestroy: testCheckARMSimpleRMLBDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: config, Check: resource.ComposeTestCheckFunc( - testCheckAzureSimpleLBExists("azurerm_simple_lb.test"), + testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + resource.TestMatchResourceAttr("azurerm_simple_lb.test", "frontend_id", justBeThere), + resource.TestMatchResourceAttr("azurerm_simple_lb.test", "backend_pool_id", justBeThere), + ), + }, + }, + }) +} + +func TestAccARMSimpleLB_updateTage(t *testing.T) { + + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureSimpleLB_tags, ri, ri) + postConfig := fmt.Sprintf(testAccAzureSimpleLB_updateTags, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckARMSimpleRMLBDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + resource.TestCheckResourceAttr( + "azurerm_simple_lb.test", "tags.#", "2"), + resource.TestCheckResourceAttr( + "azurerm_simple_lb.test", "tags.environment", "Production"), + resource.TestCheckResourceAttr( + "azurerm_simple_lb.test", "tags.cost_center", "MSFT"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + resource.TestCheckResourceAttr( + "azurerm_simple_lb.test", "tags.#", "1"), + resource.TestCheckResourceAttr( + "azurerm_simple_lb.test", "tags.environment", "staging"), ), }, }, }) } -func testCheckAzureSimpleLBExists(name string) resource.TestCheckFunc { +func testCheckARMSimpleLBExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API rs, ok := s.RootModule().Resources[name] @@ -59,7 +102,7 @@ func testCheckAzureSimpleLBExists(name string) resource.TestCheckFunc { } } -func testCheckAzureSimpleRMLBDestroy(s *terraform.State) error { +func testCheckARMSimpleRMLBDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*ArmClient).loadBalancerClient for _, rs := range s.RootModule().Resources { @@ -84,7 +127,7 @@ func testCheckAzureSimpleRMLBDestroy(s *terraform.State) error { return nil } -var testAccAzureSimpleLB_min = ` +var testAccAzureSimpleLB_basic = ` resource "azurerm_resource_group" "test" { name = "acctestlbrg-%d" location = "West US" @@ -122,3 +165,91 @@ resource "azurerm_simple_lb" "test" { } } ` + +var testAccAzureSimpleLB_tags = ` +resource "azurerm_resource_group" "test" { + name = "acctestlbrg-%d" + location = "West US" +} + +resource "azurerm_public_ip" "test" { + name = "simplelbip" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "static" +} + +resource "azurerm_simple_lb" "test" { + name = "acctestlb%d" + location = "West US" + type = "Microsoft.Network/loadBalancers" + resource_group_name = "${azurerm_resource_group.test.name}" + frontend_allocation_method = "Dynamic" + frontend_public_ip_address = "${azurerm_public_ip.test.id}" + + probe { + name = "testProbe1" + protocol = "Tcp" + port = 22 + interval = 5 + number_of_probes = 16 + } + rule { + protocol = "Tcp" + load_distribution = "Default" + frontend_port = 22 + backend_port = 22 + name = "rule1" + probe_name = "testProbe1" + } + + tags { + environment = "Production" + cost_center = "MSFT" + } +} +` + +var testAccAzureSimpleLB_updateTags = ` +resource "azurerm_resource_group" "test" { + name = "acctestlbrg-%d" + location = "West US" +} + +resource "azurerm_public_ip" "test" { + name = "simplelbip" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "static" +} + +resource "azurerm_simple_lb" "test" { + name = "acctestlb%d" + location = "West US" + type = "Microsoft.Network/loadBalancers" + resource_group_name = "${azurerm_resource_group.test.name}" + frontend_allocation_method = "Dynamic" + frontend_public_ip_address = "${azurerm_public_ip.test.id}" + + probe { + name = "testProbe1" + protocol = "Tcp" + port = 22 + interval = 5 + number_of_probes = 16 + } + rule { + protocol = "Tcp" + load_distribution = "Default" + frontend_port = 22 + backend_port = 22 + name = "rule1" + probe_name = "testProbe1" + } + + tags { + environment = "Production" + cost_center = "MSFT" + } +} +` From c9b955f44251ec8f235639330b0561f1d4c9b9e1 Mon Sep 17 00:00:00 2001 From: John Bresnahan Date: Mon, 23 May 2016 06:38:29 -1000 Subject: [PATCH 04/12] Simple LB patch: Fix update when a probe is removed. This patch allows a probe to be deleted if the load balancing rules are adjusted properly as well. --- .../azurerm/resource_arm_simple_lb.go | 163 ++++++++++++++---- .../azurerm/resource_arm_simple_lb_test.go | 143 ++++++++++++++- 2 files changed, 262 insertions(+), 44 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index 5eb625ff0426..969e7143d9a5 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -43,40 +43,46 @@ func resourceArmSimpleLb() *schema.Resource { "type": &schema.Schema{ Type: schema.TypeString, Required: true, + ForceNew: true, }, "resource_group_name": &schema.Schema{ Type: schema.TypeString, Required: true, + ForceNew: true, }, "location": &schema.Schema{ Type: schema.TypeString, Required: true, StateFunc: azureRMNormalizeLocation, + ForceNew: true, }, "frontend_private_ip_address": &schema.Schema{ Type: schema.TypeString, Optional: true, + ForceNew: true, }, "frontend_allocation_method": &schema.Schema{ Type: schema.TypeString, Required: true, ValidateFunc: validateAllocationMethod, + ForceNew: true, }, "frontend_subnet": &schema.Schema{ Type: schema.TypeString, Optional: true, + ForceNew: true, }, "frontend_public_ip_address": &schema.Schema{ Type: schema.TypeString, Optional: true, + ForceNew: true, }, "probe": &schema.Schema{ Type: schema.TypeSet, - Optional: true, - Computed: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -115,8 +121,7 @@ func resourceArmSimpleLb() *schema.Resource { "rule": &schema.Schema{ Type: schema.TypeSet, - Optional: true, - Computed: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -160,13 +165,13 @@ func resourceArmSimpleLb() *schema.Resource { func resourceARMLoadBalancerRuleHash(v interface{}) int { m := v.(map[string]interface{}) - rule := fmt.Sprintf("%s-%s-%s%d-%d", m["name"].(string), m["protocol"].(string), m["load_distribution"].(string), m["frontend_port"], m["backend_port"]) + rule := fmt.Sprintf("%s-%s-%s-%s-%d-%d", m["name"].(string), m["protocol"].(string), m["probe_name"].(string), m["load_distribution"].(string), m["frontend_port"], m["backend_port"]) return hashcode.String(rule) } func resourceARMLoadBalancerProbeHash(v interface{}) int { m := v.(map[string]interface{}) - rule := fmt.Sprintf("%s-%s-%d-%d", m["name"].(string), m["protocol"].(string), m["frontend_port"], m["backend_port"]) + rule := fmt.Sprintf("%s-%s-%d-%d-%d", m["name"].(string), m["protocol"].(string), m["port"], m["number_of_probes"], m["interval"]) if m["request_path"] != nil { rule = rule + "-" + m["request_path"].(string) } @@ -226,6 +231,16 @@ func validateLoadDistribution(v interface{}, k string) (ws []string, errors []er return } +func findRuleByName(ruleArray *[]network.LoadBalancingRule, ruleName string) (int, error) { + for i := 0; i < len(*ruleArray); i++ { + tmRule := (*ruleArray)[i] + if *tmRule.Name == ruleName { + return i, nil + } + } + return -1, fmt.Errorf("Error loading the probe named %s", ruleName) +} + func findProbeConfByName(probeArray *[]network.Probe, probeName string) (int, error) { for i := 0; i < len(*probeArray); i++ { tmpProbe := (*probeArray)[i] @@ -250,14 +265,17 @@ func pullOutLbRules(d *schema.ResourceData, loadBalancer network.LoadBalancer) ( log.Printf("[resourceArmSimpleLb] pullOutLbRules[enter]") defer log.Printf("[resourceArmSimpleLb] pullOutLbRules[exit]") - backendPoolId := d.Get("backend_pool_id").(string) - frontendIpId := d.Get("frontend_id").(string) - backendPoolRef := network.SubResource{ID: &backendPoolId} - frontendIpRef := network.SubResource{ID: &frontendIpId} + backendPoolId := *(*loadBalancer.Properties.BackendAddressPools)[0].ID + frontendIpId := *(*loadBalancer.Properties.FrontendIPConfigurations)[0].ID // then; the subnets: outRules := []network.LoadBalancingRule{} - if rules := d.Get("rule").(*schema.Set); rules.Len() > 0 { + + log.Printf("[resourceArmSimpleLb] pullOutLbRules will use frontend %s and backend %s", frontendIpId, backendPoolId) + rules := d.Get("rule").(*schema.Set) + + if rules.Len() > 0 { + log.Printf("[resourceArmSimpleLb] pullOutLbRules found %d rules in plan", rules.Len()) for _, rule := range rules.List() { rule := rule.(map[string]interface{}) @@ -273,8 +291,19 @@ func pullOutLbRules(d *schema.ResourceData, loadBalancer network.LoadBalancer) ( return nil, err } + backendPoolRef := network.SubResource{ID: &backendPoolId} + frontendIpRef := network.SubResource{ID: &frontendIpId} probeRef := network.SubResource{ID: (*loadBalancer.Properties.Probes)[i].ID} + log.Printf("[resourceArmSimpleLb] pullOutLbRules rule %s is using probe %s", ruleName, *(*loadBalancer.Properties.Probes)[i].ID) + + var ruleId *string = nil + ruleNdx, err := findRuleByName(loadBalancer.Properties.LoadBalancingRules, ruleName) + if err == nil { + log.Printf("[resourceArmSimpleLb] pullOutLbRules found the existing rule %s", ruleName) + ruleId = (*loadBalancer.Properties.LoadBalancingRules)[ruleNdx].ID + } + props := network.LoadBalancingRulePropertiesFormat{ Protocol: network.TransportProtocol(ruleProtocol), LoadDistribution: network.LoadDistribution(loadDistribution), @@ -287,9 +316,12 @@ func pullOutLbRules(d *schema.ResourceData, loadBalancer network.LoadBalancer) ( ruleObj := network.LoadBalancingRule{ Name: &ruleName, Properties: &props, + ID: ruleId, } outRules = append(outRules, ruleObj) } + } else { + log.Printf("[resourceArmSimpleLb] pullOutLbRules no rules found") } return &outRules, nil @@ -414,18 +446,18 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { backendPoolConfs := []network.BackendAddressPool{} backendPoolConfs = append(backendPoolConfs, backendpool) loadBalancer.Properties.BackendAddressPools = &backendPoolConfs + //loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} resp, err := lbClient.CreateOrUpdate(resGrp, name, loadBalancer) if err != nil { log.Printf("[resourceArmSimpleLb] ERROR LB got status %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) } - log.Printf("[resourceArmSimpleLb] Create LB got status %d", resp.StatusCode) + log.Printf("[resourceArmSimpleLb] Create LB got status %d. Provision State %s", resp.StatusCode, *resp.Properties.ProvisioningState) - d.SetId(*resp.ID) - err = iResourceArmSimpleLbRead(d, meta) - if err != nil { - return err + //Possible status values are Updating|Deleting|Failed|Succeeded + if *resp.Properties.ProvisioningState != "Succeeded" { + return fmt.Errorf("The load balancer was not properly deployed. The provisioning state %s", *resp.Properties.ProvisioningState) } log.Printf("[resourceArmSimpleLb] We have the IDs now updating to set rules") @@ -433,13 +465,16 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } + log.Printf("[resourceArmSimpleLb] created %d rules", len(*loadBalancer.Properties.LoadBalancingRules)) + resp, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer) if err != nil { - log.Printf("[resourceArmSimpleLb] ERROR LB got status %s", err.Error()) + log.Printf("[resourceArmSimpleLb] ERROR When trying to set the rules. LB got status %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) } + log.Printf("[resourceArmSimpleLb] Set the rules on the LB. Provision State %s", *resp.Properties.ProvisioningState) - return iResourceArmSimpleLbRead(d, meta) + return flattenAllOfLb(resp, d, meta) } func flattenAzureRmFrontendIp(frontenIpArray []network.FrontendIPConfiguration, d *schema.ResourceData) error { @@ -470,8 +505,8 @@ func flattenAzureRmFrontendIp(frontenIpArray []network.FrontendIPConfiguration, } func flattenAzureRmLoadBalancerRules(loadBalancer network.LoadBalancer, d *schema.ResourceData) error { - log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[enter]") - defer log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[exit]") + log.Printf("[resourceArmSimpleLb] flattenAzureRmLoadBalancerRules[enter]") + defer log.Printf("[resourceArmSimpleLb] flattenAzureRmLoadBalancerRules[exit]") loadBalancingRuleArray := loadBalancer.Properties.LoadBalancingRules @@ -479,9 +514,12 @@ func flattenAzureRmLoadBalancerRules(loadBalancer network.LoadBalancer, d *schem F: resourceARMLoadBalancerProbeHash, } + log.Printf("[resourceArmSimpleLb] flattenAzureRmLoadBalancerRules found %d rules", len(*loadBalancingRuleArray)) + for _, rule := range *loadBalancingRuleArray { r := map[string]interface{}{} + log.Printf("[resourceArmSimpleLb] Found LB RULE %s", *rule.Name) r["name"] = *rule.Name r["rule_id"] = *rule.ID if rule.Properties != nil { @@ -499,7 +537,7 @@ func flattenAzureRmLoadBalancerRules(loadBalancer network.LoadBalancer, d *schem } ruleSet.Add(r) } - d.Set("subnet", ruleSet) + d.Set("rule", ruleSet) return nil } @@ -529,7 +567,7 @@ func flattenAzureRmProbe(probeArray *[]network.Probe, d *schema.ResourceData) er probeSet.Add(p) } - d.Set("subnet", probeSet) + d.Set("probe", probeSet) return nil } @@ -538,7 +576,60 @@ func resourceArmSimpleLbUpdate(d *schema.ResourceData, meta interface{}) error { log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbUpdate[enter]") defer log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbUpdate[exit]") - return resourceArmSimpleLbCreate(d, meta) + lbClient := meta.(*ArmClient).loadBalancerClient + + // first; fetch a bunch of fields: + name := d.Get("name").(string) + resGrp := d.Get("resource_group_name").(string) + tags := d.Get("tags").(map[string]interface{}) + + loadBalancer, err := lbClient.Get(resGrp, name, "") + if err != nil { + return fmt.Errorf("Error could not find the LB %s. %s", name, err) + } + + loadBalancer.Tags = expandTags(tags) + + probes, err := pullOutProbes(d) + if err != nil { + return err + } + loadBalancer.Properties.Probes = probes + + new_backend_pool_name := fmt.Sprintf("%sbackendpool", name) + backendpool := network.BackendAddressPool{Name: &new_backend_pool_name} + backendPoolConfs := []network.BackendAddressPool{} + backendPoolConfs = append(backendPoolConfs, backendpool) + loadBalancer.Properties.BackendAddressPools = &backendPoolConfs + loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} + + resp, err := lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR Update LB got status %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) + } + log.Printf("[resourceArmSimpleLb] Update LB got status %d. Provision State %s", resp.StatusCode, *resp.Properties.ProvisioningState) + + //Possible status values are Updating|Deleting|Failed|Succeeded + if *resp.Properties.ProvisioningState != "Succeeded" { + return fmt.Errorf("The load balancer was not properly deployed. The provisioning state %s", *resp.Properties.ProvisioningState) + } + + log.Printf("[resourceArmSimpleLb] We have the IDs now updating to set rules") + loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d, resp) + if err != nil { + return err + } + log.Printf("[resourceArmSimpleLb] created %d rules", len(*loadBalancer.Properties.LoadBalancingRules)) + + resp, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR When trying to set the rules. Update LB got status %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) + } + log.Printf("[resourceArmSimpleLb] Set the rules on the LB. Provision State %s", *resp.Properties.ProvisioningState) + + return flattenAllOfLb(resp, d, meta) } func resourceArmSimpleLbDelete(d *schema.ResourceData, meta interface{}) error { @@ -563,9 +654,9 @@ func resourceArmSimpleLbDelete(d *schema.ResourceData, meta interface{}) error { } // resourceArmLoadBalancerRead goes ahead and reads the state of the corresponding ARM load balancer. -func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { - log.Printf("[resourceArmSimpleLb] iResourceArmSimpleLbRead[enter]") - defer log.Printf("[resourceArmSimpleLb] iResourceArmSimpleLbRead[exit]") +func resourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { + log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbRead[enter]") + defer log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbRead[exit]") lbClient := meta.(*ArmClient).loadBalancerClient @@ -579,6 +670,14 @@ func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error reading the state of the load balancer off Azure: %s", err) } + return flattenAllOfLb(loadBalancer, d, meta) +} + +// resourceArmLoadBalancerRead goes ahead and reads the state of the corresponding ARM load balancer. +func flattenAllOfLb(loadBalancer network.LoadBalancer, d *schema.ResourceData, meta interface{}) error { + log.Printf("[resourceArmSimpleLb] flattenAllOfLb[enter]") + defer log.Printf("[resourceArmSimpleLb] flattenAllOfLb[exit]") + log.Printf("[INFO] Succesfully retrieved details for load balancer '%s'.", *loadBalancer.Name) fip := loadBalancer.Properties.FrontendIPConfigurations @@ -586,7 +685,7 @@ func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { d.Set("location", loadBalancer.Location) d.Set("type", loadBalancer.Type) - err = flattenAzureRmFrontendIp(*fip, d) + err := flattenAzureRmFrontendIp(*fip, d) if err != nil { return err } @@ -608,13 +707,7 @@ func iResourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { } flattenAndSetTags(d, loadBalancer.Tags) - return nil -} - -// resourceArmLoadBalancerRead goes ahead and reads the state of the corresponding ARM load balancer. -func resourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { - log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbRead[enter]") - defer log.Printf("[resourceArmSimpleLb] resourceArmSimpleLbRead[exit]") + d.SetId(*loadBalancer.ID) - return iResourceArmSimpleLbRead(d, meta) + return nil } diff --git a/builtin/providers/azurerm/resource_arm_simple_lb_test.go b/builtin/providers/azurerm/resource_arm_simple_lb_test.go index 2a17d88dc48a..cca9734626d6 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb_test.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb_test.go @@ -14,7 +14,7 @@ import ( func TestAccARMSimpleLB_basic(t *testing.T) { ri := acctest.RandInt() - config := fmt.Sprintf(testAccAzureSimpleLB_basic, ri, ri) + config := fmt.Sprintf(testAccAzureSimpleLB_basic, ri, ri, ri) justBeThere := regexp.MustCompile(".*") @@ -35,11 +35,11 @@ func TestAccARMSimpleLB_basic(t *testing.T) { }) } -func TestAccARMSimpleLB_updateTage(t *testing.T) { +func TestAccARMSimpleLB_updateTag(t *testing.T) { ri := acctest.RandInt() - preConfig := fmt.Sprintf(testAccAzureSimpleLB_tags, ri, ri) - postConfig := fmt.Sprintf(testAccAzureSimpleLB_updateTags, ri, ri) + preConfig := fmt.Sprintf(testAccAzureSimpleLB_tags, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureSimpleLB_updateTags, ri, ri, ri) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -73,6 +73,38 @@ func TestAccARMSimpleLB_updateTage(t *testing.T) { }) } +func TestAccARMSimpleLB_updateProbe(t *testing.T) { + + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureSimpleLB_probe, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureSimpleLB_probeUpdate, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckARMSimpleRMLBDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + resource.TestCheckResourceAttr( + "azurerm_simple_lb.test", "probe.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + resource.TestCheckResourceAttr( + "azurerm_simple_lb.test", "probe.#", "1"), + ), + }, + }, + }) +} + func testCheckARMSimpleLBExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API @@ -134,7 +166,7 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_public_ip" "test" { - name = "simplelbip" + name = "simplelbip%d" location = "West US" resource_group_name = "${azurerm_resource_group.test.name}" public_ip_address_allocation = "static" @@ -173,7 +205,7 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_public_ip" "test" { - name = "simplelbip" + name = "simplelbip%d" location = "West US" resource_group_name = "${azurerm_resource_group.test.name}" public_ip_address_allocation = "static" @@ -217,7 +249,7 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_public_ip" "test" { - name = "simplelbip" + name = "simplelbip%d" location = "West US" resource_group_name = "${azurerm_resource_group.test.name}" public_ip_address_allocation = "static" @@ -248,8 +280,101 @@ resource "azurerm_simple_lb" "test" { } tags { - environment = "Production" - cost_center = "MSFT" + environment = "staging" + } +} +` + +var testAccAzureSimpleLB_probe = ` +resource "azurerm_resource_group" "test" { + name = "acctestlbrg-%d" + location = "West US" +} + +resource "azurerm_public_ip" "test" { + name = "simplelbip%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "static" +} + +resource "azurerm_simple_lb" "test" { + name = "acctestlb%d" + location = "West US" + type = "Microsoft.Network/loadBalancers" + resource_group_name = "${azurerm_resource_group.test.name}" + frontend_allocation_method = "Dynamic" + frontend_public_ip_address = "${azurerm_public_ip.test.id}" + + probe { + name = "testProbe1" + protocol = "Tcp" + port = 22 + interval = 5 + number_of_probes = 16 + } + rule { + protocol = "Tcp" + load_distribution = "Default" + frontend_port = 22 + backend_port = 22 + name = "rule1" + probe_name = "testProbe1" + } + + probe { + name = "testProbe2" + protocol = "Tcp" + port = 80 + interval = 5 + number_of_probes = 16 + } + rule { + protocol = "Tcp" + load_distribution = "Default" + frontend_port = 80 + backend_port = 80 + name = "rule2" + probe_name = "testProbe2" + } +} +` + +var testAccAzureSimpleLB_probeUpdate = ` +resource "azurerm_resource_group" "test" { + name = "acctestlbrg-%d" + location = "West US" +} + +resource "azurerm_public_ip" "test" { + name = "simplelbip%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "static" +} + +resource "azurerm_simple_lb" "test" { + name = "acctestlb%d" + location = "West US" + type = "Microsoft.Network/loadBalancers" + resource_group_name = "${azurerm_resource_group.test.name}" + frontend_allocation_method = "Dynamic" + frontend_public_ip_address = "${azurerm_public_ip.test.id}" + + probe { + name = "testProbe1" + protocol = "Tcp" + port = 22 + interval = 5 + number_of_probes = 16 + } + rule { + protocol = "Tcp" + load_distribution = "Default" + frontend_port = 22 + backend_port = 22 + name = "rule1" + probe_name = "testProbe1" } } ` From ded84104f26e3e130285e699861a31d53d919584 Mon Sep 17 00:00:00 2001 From: Maxime Bury Date: Tue, 24 May 2016 14:52:32 +0200 Subject: [PATCH 05/12] Fix up hashes, cleanup validation --- .../resource_arm_network_interface_card.go | 6 + .../azurerm/resource_arm_simple_lb.go | 208 +++++++----------- builtin/providers/azurerm/util.go | 24 ++ 3 files changed, 113 insertions(+), 125 deletions(-) create mode 100644 builtin/providers/azurerm/util.go diff --git a/builtin/providers/azurerm/resource_arm_network_interface_card.go b/builtin/providers/azurerm/resource_arm_network_interface_card.go index 8e6771541d01..371b99a7a253 100644 --- a/builtin/providers/azurerm/resource_arm_network_interface_card.go +++ b/builtin/providers/azurerm/resource_arm_network_interface_card.go @@ -328,6 +328,12 @@ func resourceArmNetworkInterfaceIpConfigurationHash(v interface{}) int { if m["public_ip_address_id"] != nil { buf.WriteString(fmt.Sprintf("%s-", m["public_ip_address_id"].(string))) } + if m["load_balancer_backend_address_pools_ids"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["load_balancer_backend_address_pools_ids"].(*schema.Set).GoString())) + } + if m["load_balancer_inbound_nat_rules_ids"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["load_balancer_inbound_nat_rules_ids"].(*schema.Set).GoString())) + } return hashcode.String(buf.String()) } diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index 969e7143d9a5..cb5044cea939 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -2,11 +2,12 @@ package azurerm import ( "fmt" + "log" + "strings" + "github.com/Azure/azure-sdk-for-go/arm/network" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" - "log" - "strings" ) // resourceArmLoadBalancer returns the *schema.Resource @@ -166,7 +167,7 @@ func resourceArmSimpleLb() *schema.Resource { func resourceARMLoadBalancerRuleHash(v interface{}) int { m := v.(map[string]interface{}) rule := fmt.Sprintf("%s-%s-%s-%s-%d-%d", m["name"].(string), m["protocol"].(string), m["probe_name"].(string), m["load_distribution"].(string), m["frontend_port"], m["backend_port"]) - return hashcode.String(rule) + return hashcode.String(strings.ToLower(rule)) } func resourceARMLoadBalancerProbeHash(v interface{}) int { @@ -175,153 +176,119 @@ func resourceARMLoadBalancerProbeHash(v interface{}) int { if m["request_path"] != nil { rule = rule + "-" + m["request_path"].(string) } - return hashcode.String(rule) + return hashcode.String(strings.ToLower(rule)) } -func validateAllocationMethod(v interface{}, k string) (ws []string, errors []error) { - value := strings.ToLower(v.(string)) - allocations := map[string]bool{ - "static": true, - "dynamic": true, - } - - if !allocations[value] { +func validateAllocationMethod(allocation interface{}, k string) (ws []string, errors []error) { + if !isOneOf([]string{"static", "dynamic"}, allocation) { errors = append(errors, fmt.Errorf("Allocation method can only be Static or Dynamic")) } return } -func validateProtocolType(v interface{}, k string) (ws []string, errors []error) { - value := strings.ToLower(v.(string)) - allocations := map[string]bool{ - "tcp": true, - "udp": true, - } - - if !allocations[value] { +func validateProtocolType(protocol interface{}, k string) (ws []string, errors []error) { + if !isOneOf([]string{"tcp", "udp"}, protocol) { errors = append(errors, fmt.Errorf("Protocol can only be tcp or udp")) } return } -func validateProbeProtocolType(v interface{}, k string) (ws []string, errors []error) { - value := strings.ToLower(v.(string)) - allocations := map[string]bool{ - "tcp": true, - "http": true, - } - - if !allocations[value] { - errors = append(errors, fmt.Errorf("Protocol can only be tcp or udp")) +func validateProbeProtocolType(protocol interface{}, k string) (ws []string, errors []error) { + if !isOneOf([]string{"tcp", "http"}, protocol) { + errors = append(errors, fmt.Errorf("Protocol can only be tcp or http")) } return } -func validateLoadDistribution(v interface{}, k string) (ws []string, errors []error) { - value := strings.ToLower(v.(string)) - allocations := map[string]bool{ - "default": true, - "sourceip": true, - "sourceipprotocol": true, - } - - if !allocations[value] { +func validateLoadDistribution(distribution interface{}, k string) (ws []string, errors []error) { + if !isOneOf([]string{"default", "sourceip", "sourceipprotocol"}, distribution) { errors = append(errors, fmt.Errorf("Load Distribution can only be default, sourceIp, or sourceIpProtocol")) } return } -func findRuleByName(ruleArray *[]network.LoadBalancingRule, ruleName string) (int, error) { - for i := 0; i < len(*ruleArray); i++ { - tmRule := (*ruleArray)[i] - if *tmRule.Name == ruleName { - return i, nil +func findRuleByName(ruleArray *[]network.LoadBalancingRule, ruleName string) (network.LoadBalancingRule, error) { + for _, rule := range *ruleArray { + if *rule.Name == ruleName { + log.Printf("[findRuleByName] found rule %v", rule) + return rule, nil } } - return -1, fmt.Errorf("Error loading the probe named %s", ruleName) + return network.LoadBalancingRule{}, fmt.Errorf("Error loading the rule named %s", ruleName) } -func findProbeConfByName(probeArray *[]network.Probe, probeName string) (int, error) { - for i := 0; i < len(*probeArray); i++ { - tmpProbe := (*probeArray)[i] - if *tmpProbe.Name == probeName { - return i, nil +func findProbeByName(probeArray *[]network.Probe, probeName string) (network.Probe, error) { + for _, probe := range *probeArray { + if *probe.Name == probeName { + log.Printf("[findProbeByName] found probe %v", probe) + return probe, nil } } - return -1, fmt.Errorf("Error loading the probe named %s", probeName) + + return network.Probe{}, fmt.Errorf("Error loading the probe named %s", probeName) } -func findProbeConfById(probeArray *[]network.Probe, probeId string) (int, error) { - for i := 0; i < len(*probeArray); i++ { - tmpProbe := (*probeArray)[i] - if *tmpProbe.ID == probeId { - return i, nil +func findProbeById(probeArray *[]network.Probe, probeId string) (network.Probe, error) { + for _, probe := range *probeArray { + if *probe.ID == probeId { + log.Printf("[findProbeById] found probe %v", probe) + return probe, nil } } - return -1, fmt.Errorf("Error finding the probe ID %s", probeId) + + return network.Probe{}, fmt.Errorf("Error finding the probe with ID %s", probeId) } func pullOutLbRules(d *schema.ResourceData, loadBalancer network.LoadBalancer) (*[]network.LoadBalancingRule, error) { log.Printf("[resourceArmSimpleLb] pullOutLbRules[enter]") defer log.Printf("[resourceArmSimpleLb] pullOutLbRules[exit]") - backendPoolId := *(*loadBalancer.Properties.BackendAddressPools)[0].ID - frontendIpId := *(*loadBalancer.Properties.FrontendIPConfigurations)[0].ID - - // then; the subnets: + log.Printf("[resourceArmSimpleLb] pullOutLbRules %v", *loadBalancer.Properties.Probes) outRules := []network.LoadBalancingRule{} - log.Printf("[resourceArmSimpleLb] pullOutLbRules will use frontend %s and backend %s", frontendIpId, backendPoolId) - rules := d.Get("rule").(*schema.Set) - - if rules.Len() > 0 { - log.Printf("[resourceArmSimpleLb] pullOutLbRules found %d rules in plan", rules.Len()) - for _, rule := range rules.List() { - rule := rule.(map[string]interface{}) - - ruleName := rule["name"].(string) - ruleProtocol := rule["protocol"].(string) - ruleProbeName := rule["probe_name"].(string) - loadDistribution := rule["load_distribution"].(string) - frontendPort := rule["frontend_port"].(int) - backendendPort := rule["backend_port"].(int) + backendPoolID := (*loadBalancer.Properties.BackendAddressPools)[0].ID + frontendIpID := (*loadBalancer.Properties.FrontendIPConfigurations)[0].ID + log.Printf("[resourceArmSimpleLb] pullOutLbRules will use frontend %s and backend %s", *frontendIpID, *backendPoolID) - i, err := findProbeConfByName(loadBalancer.Properties.Probes, ruleProbeName) - if err != nil { - return nil, err - } + rules := d.Get("rule").(*schema.Set) + if rules.Len() == 0 { + log.Printf("[resourceArmSimpleLb] pullOutLbRules no rules found") + return &outRules, nil + } - backendPoolRef := network.SubResource{ID: &backendPoolId} - frontendIpRef := network.SubResource{ID: &frontendIpId} - probeRef := network.SubResource{ID: (*loadBalancer.Properties.Probes)[i].ID} + log.Printf("[resourceArmSimpleLb] pullOutLbRules found %d rules in plan", rules.Len()) + for _, rule := range rules.List() { + rule := rule.(map[string]interface{}) + log.Printf("[resourceArmSimpleLb] pullOutLbRules %v", rule) - log.Printf("[resourceArmSimpleLb] pullOutLbRules rule %s is using probe %s", ruleName, *(*loadBalancer.Properties.Probes)[i].ID) + ruleName := rule["name"].(string) - var ruleId *string = nil - ruleNdx, err := findRuleByName(loadBalancer.Properties.LoadBalancingRules, ruleName) - if err == nil { - log.Printf("[resourceArmSimpleLb] pullOutLbRules found the existing rule %s", ruleName) - ruleId = (*loadBalancer.Properties.LoadBalancingRules)[ruleNdx].ID - } + existingRule, err := findRuleByName(loadBalancer.Properties.LoadBalancingRules, ruleName) + if err == nil { + log.Printf("[resourceArmSimpleLb] pullOutLbRules found the existing rule %s", ruleName) + } - props := network.LoadBalancingRulePropertiesFormat{ - Protocol: network.TransportProtocol(ruleProtocol), - LoadDistribution: network.LoadDistribution(loadDistribution), - FrontendPort: &frontendPort, - BackendPort: &backendendPort, - Probe: &probeRef, - BackendAddressPool: &backendPoolRef, - FrontendIPConfiguration: &frontendIpRef, - } - ruleObj := network.LoadBalancingRule{ - Name: &ruleName, - Properties: &props, - ID: ruleId, - } - outRules = append(outRules, ruleObj) + probe, err := findProbeByName(loadBalancer.Properties.Probes, rule["probe_name"].(string)) + if err != nil { + return nil, err } - } else { - log.Printf("[resourceArmSimpleLb] pullOutLbRules no rules found") + log.Printf("[resourceArmSimpleLb] pullOutLbRules rule %s is using probe %s", ruleName, *probe.ID) + + props := network.LoadBalancingRulePropertiesFormat{ + Protocol: network.TransportProtocol(rule["protocol"].(string)), + LoadDistribution: network.LoadDistribution(rule["load_distribution"].(string)), + FrontendPort: Int(rule["frontend_port"]), + BackendPort: Int(rule["backend_port"]), + Probe: &network.SubResource{ID: probe.ID}, + BackendAddressPool: &network.SubResource{ID: backendPoolID}, + FrontendIPConfiguration: &network.SubResource{ID: frontendIpID}, + } + + outRules = append(outRules, network.LoadBalancingRule{ + Name: &ruleName, + Properties: &props, + ID: existingRule.ID, + }) } return &outRules, nil @@ -331,34 +298,25 @@ func pullOutProbes(d *schema.ResourceData) (*[]network.Probe, error) { log.Printf("[resourceArmSimpleLb] pullOutProbes[enter]") defer log.Printf("[resourceArmSimpleLb] pullOutProbes[exit]") - // then; the subnets: outProbes := []network.Probe{} if probes := d.Get("probe").(*schema.Set); probes.Len() > 0 { for _, probe := range probes.List() { probe := probe.(map[string]interface{}) - probeName := probe["name"].(string) - ruleProtocol := probe["protocol"].(string) - requestPath := probe["request_path"].(string) - port := probe["port"].(int) - interval := probe["interval"].(int) - numberOfProbes := probe["number_of_probes"].(int) - probeProps := network.ProbePropertiesFormat{ - Protocol: network.ProbeProtocol(ruleProtocol), - Port: &port, - IntervalInSeconds: &interval, - NumberOfProbes: &numberOfProbes, + Protocol: network.ProbeProtocol(probe["protocol"].(string)), + Port: Int(probe["port"]), + IntervalInSeconds: Int(probe["interval"]), + NumberOfProbes: Int(probe["number_of_probes"]), } - if requestPath != "" { + if requestPath := probe["request_path"].(string); requestPath != "" { probeProps.RequestPath = &requestPath } - probeObj := network.Probe{ - Name: &probeName, + outProbes = append(outProbes, network.Probe{ + Name: String(probe["name"]), Properties: &probeProps, - } - outProbes = append(outProbes, probeObj) + }) } } @@ -446,7 +404,7 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { backendPoolConfs := []network.BackendAddressPool{} backendPoolConfs = append(backendPoolConfs, backendpool) loadBalancer.Properties.BackendAddressPools = &backendPoolConfs - //loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} + loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} resp, err := lbClient.CreateOrUpdate(resGrp, name, loadBalancer) if err != nil { @@ -529,11 +487,11 @@ func flattenAzureRmLoadBalancerRules(loadBalancer network.LoadBalancer, d *schem r["backend_port"] = *rule.Properties.BackendPort ruleProbeID := *rule.Properties.Probe.ID - i, err := findProbeConfById(loadBalancer.Properties.Probes, ruleProbeID) + conf, err := findProbeById(loadBalancer.Properties.Probes, ruleProbeID) if err != nil { return err } - r["probe_name"] = *(*loadBalancer.Properties.Probes)[i].Name + r["probe_name"] = *conf.Name } ruleSet.Add(r) } diff --git a/builtin/providers/azurerm/util.go b/builtin/providers/azurerm/util.go new file mode 100644 index 000000000000..a9809b0af854 --- /dev/null +++ b/builtin/providers/azurerm/util.go @@ -0,0 +1,24 @@ +package azurerm + +import "strings" + +func String(value interface{}) *string { + s := value.(string) + return &s +} + +func Int(value interface{}) *int { + i := value.(int) + return &i +} + +func isOneOf(haystack []string, needle interface{}) bool { + n := strings.ToLower(needle.(string)) + for _, h := range haystack { + if h == n { + return true + } + } + + return false +} From 8905f75b7a354abc9945f0c8457e1f6cc39b3a47 Mon Sep 17 00:00:00 2001 From: Maxime Bury Date: Wed, 8 Jun 2016 14:58:08 -0700 Subject: [PATCH 06/12] Don't error if lb was externally removed --- builtin/providers/azurerm/resource_arm_simple_lb.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index cb5044cea939..930d8a673e42 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -625,6 +625,10 @@ func resourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { loadBalancer, err := lbClient.Get(resGrp, name, "") if err != nil { + if loadBalancer.StatusCode == 404 { + d.SetId("") + return nil + } return fmt.Errorf("Error reading the state of the load balancer off Azure: %s", err) } From f8e22ed4afa73dfd11d4d2e2d7ca94ce5a87064c Mon Sep 17 00:00:00 2001 From: John Bresnahan Date: Wed, 15 Jun 2016 09:46:45 -0500 Subject: [PATCH 07/12] Updating the simple load balancer to the new azure sdk --- builtin/providers/azurerm/provider.go | 1 - .../azurerm/resource_arm_simple_lb.go | 58 ++++++++++++------- builtin/providers/azurerm/util.go | 6 ++ 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index e48d5e05bed2..bc0608498349 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -81,7 +81,6 @@ func Provider() terraform.ResourceProvider { "azurerm_sql_firewall_rule": resourceArmSqlFirewallRule(), "azurerm_sql_server": resourceArmSqlServer(), "azurerm_simple_lb": resourceArmSimpleLb(), ->>>>>>> A simplifed load balancer resource for AzureRM }, ConfigureFunc: providerConfigure, } diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index 930d8a673e42..c980faf1fdfc 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -277,8 +277,8 @@ func pullOutLbRules(d *schema.ResourceData, loadBalancer network.LoadBalancer) ( props := network.LoadBalancingRulePropertiesFormat{ Protocol: network.TransportProtocol(rule["protocol"].(string)), LoadDistribution: network.LoadDistribution(rule["load_distribution"].(string)), - FrontendPort: Int(rule["frontend_port"]), - BackendPort: Int(rule["backend_port"]), + FrontendPort: Int32(rule["frontend_port"]), + BackendPort: Int32(rule["backend_port"]), Probe: &network.SubResource{ID: probe.ID}, BackendAddressPool: &network.SubResource{ID: backendPoolID}, FrontendIPConfiguration: &network.SubResource{ID: frontendIpID}, @@ -305,9 +305,9 @@ func pullOutProbes(d *schema.ResourceData) (*[]network.Probe, error) { probeProps := network.ProbePropertiesFormat{ Protocol: network.ProbeProtocol(probe["protocol"].(string)), - Port: Int(probe["port"]), - IntervalInSeconds: Int(probe["interval"]), - NumberOfProbes: Int(probe["number_of_probes"]), + Port: Int32(probe["port"]), + IntervalInSeconds: Int32(probe["interval"]), + NumberOfProbes: Int32(probe["number_of_probes"]), } if requestPath := probe["request_path"].(string); requestPath != "" { probeProps.RequestPath = &requestPath @@ -406,33 +406,39 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { loadBalancer.Properties.BackendAddressPools = &backendPoolConfs loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} - resp, err := lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + cancelChannel := make(<-chan struct{}) + _, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer, cancelChannel) if err != nil { log.Printf("[resourceArmSimpleLb] ERROR LB got status %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) } - log.Printf("[resourceArmSimpleLb] Create LB got status %d. Provision State %s", resp.StatusCode, *resp.Properties.ProvisioningState) + respLb, err := lbClient.Get(resGrp, name, "") + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR LB retrieving load balancer %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM get request for load balancer '%s': %s", name, err) + } + log.Printf("[resourceArmSimpleLb] Create LB got status %d. Provision State %s", respLb.StatusCode, *respLb.Properties.ProvisioningState) //Possible status values are Updating|Deleting|Failed|Succeeded - if *resp.Properties.ProvisioningState != "Succeeded" { - return fmt.Errorf("The load balancer was not properly deployed. The provisioning state %s", *resp.Properties.ProvisioningState) + if *respLb.Properties.ProvisioningState != "Succeeded" { + log.Printf("[resourceArmSimpleLb] ERROR retrieving load balancer, provisioning state %s", *respLb.Properties.ProvisioningState) + return fmt.Errorf("ERROR retrieving load balancer, provisioning state %s", *respLb.Properties.ProvisioningState) } log.Printf("[resourceArmSimpleLb] We have the IDs now updating to set rules") - loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d, resp) + loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d, respLb) if err != nil { return err } log.Printf("[resourceArmSimpleLb] created %d rules", len(*loadBalancer.Properties.LoadBalancingRules)) - resp, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + _, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer, cancelChannel) if err != nil { log.Printf("[resourceArmSimpleLb] ERROR When trying to set the rules. LB got status %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) } - log.Printf("[resourceArmSimpleLb] Set the rules on the LB. Provision State %s", *resp.Properties.ProvisioningState) - return flattenAllOfLb(resp, d, meta) + return flattenAllOfLb(respLb, d, meta) } func flattenAzureRmFrontendIp(frontenIpArray []network.FrontendIPConfiguration, d *schema.ResourceData) error { @@ -561,33 +567,40 @@ func resourceArmSimpleLbUpdate(d *schema.ResourceData, meta interface{}) error { loadBalancer.Properties.BackendAddressPools = &backendPoolConfs loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} - resp, err := lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + cancelChannel := make(<-chan struct{}) + resp, err := lbClient.CreateOrUpdate(resGrp, name, loadBalancer, cancelChannel) if err != nil { log.Printf("[resourceArmSimpleLb] ERROR Update LB got status %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) } - log.Printf("[resourceArmSimpleLb] Update LB got status %d. Provision State %s", resp.StatusCode, *resp.Properties.ProvisioningState) + respLb, err := lbClient.Get(resGrp, name, "") + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR LB retrieving load balancer %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM get request for load balancer '%s': %s", name, err) + } + + log.Printf("[resourceArmSimpleLb] Update LB got status %d. Provision State %s", resp.StatusCode, *respLb.Properties.ProvisioningState) //Possible status values are Updating|Deleting|Failed|Succeeded - if *resp.Properties.ProvisioningState != "Succeeded" { - return fmt.Errorf("The load balancer was not properly deployed. The provisioning state %s", *resp.Properties.ProvisioningState) + if *respLb.Properties.ProvisioningState != "Succeeded" { + return fmt.Errorf("The load balancer was not properly deployed. The provisioning state %s", *respLb.Properties.ProvisioningState) } log.Printf("[resourceArmSimpleLb] We have the IDs now updating to set rules") - loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d, resp) + loadBalancer.Properties.LoadBalancingRules, err = pullOutLbRules(d, respLb) if err != nil { return err } log.Printf("[resourceArmSimpleLb] created %d rules", len(*loadBalancer.Properties.LoadBalancingRules)) - resp, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer) + resp, err = lbClient.CreateOrUpdate(resGrp, name, loadBalancer, cancelChannel) if err != nil { log.Printf("[resourceArmSimpleLb] ERROR When trying to set the rules. Update LB got status %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) } - log.Printf("[resourceArmSimpleLb] Set the rules on the LB. Provision State %s", *resp.Properties.ProvisioningState) + log.Printf("[resourceArmSimpleLb] Set the rules on the LB. Provision State %s", *respLb.Properties.ProvisioningState) - return flattenAllOfLb(resp, d, meta) + return flattenAllOfLb(respLb, d, meta) } func resourceArmSimpleLbDelete(d *schema.ResourceData, meta interface{}) error { @@ -601,7 +614,8 @@ func resourceArmSimpleLbDelete(d *schema.ResourceData, meta interface{}) error { log.Printf("[INFO] Issuing deletion request to Azure ARM for load balancer '%s'.", name) - resp, err := lbClient.Delete(resGroup, name) + cancelChannel := make(<-chan struct{}) + resp, err := lbClient.Delete(resGroup, name, cancelChannel) if err != nil { return fmt.Errorf("Error issuing Azure ARM delete request for load balancer '%s': %s", name, err) } diff --git a/builtin/providers/azurerm/util.go b/builtin/providers/azurerm/util.go index a9809b0af854..60506bffb09f 100644 --- a/builtin/providers/azurerm/util.go +++ b/builtin/providers/azurerm/util.go @@ -12,6 +12,12 @@ func Int(value interface{}) *int { return &i } +func Int32(value interface{}) *int32 { + i := value.(int) + i32 := int32(i) + return &i32 +} + func isOneOf(haystack []string, needle interface{}) bool { n := strings.ToLower(needle.(string)) for _, h := range haystack { From 9b8642c8066ed5bfeb7c731a61727075358cee0b Mon Sep 17 00:00:00 2001 From: Peter McAtominey Date: Tue, 12 Jul 2016 14:37:52 +0100 Subject: [PATCH 08/12] provider/azurerm: make azurerm_simple_lb frontend_private_ip_address Computed --- .../azurerm/resource_arm_simple_lb.go | 1 + .../azurerm/resource_arm_simple_lb_test.go | 72 ++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index c980faf1fdfc..beac4f160466 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -63,6 +63,7 @@ func resourceArmSimpleLb() *schema.Resource { Type: schema.TypeString, Optional: true, ForceNew: true, + Computed: true, }, "frontend_allocation_method": &schema.Schema{ Type: schema.TypeString, diff --git a/builtin/providers/azurerm/resource_arm_simple_lb_test.go b/builtin/providers/azurerm/resource_arm_simple_lb_test.go index cca9734626d6..175caeae89c5 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb_test.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb_test.go @@ -5,10 +5,11 @@ import ( "net/http" "testing" + "regexp" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "regexp" ) func TestAccARMSimpleLB_basic(t *testing.T) { @@ -105,6 +106,28 @@ func TestAccARMSimpleLB_updateProbe(t *testing.T) { }) } +func TestAccAzureRMSimpleLB_dynamicFrontEndIPAddress(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMSimpleLB_dynamicFrontEndIPAddress, ri, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckARMSimpleRMLBDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + }, + { + Config: config, + // left here to make it explicit that we expect an empty plan + ExpectNonEmptyPlan: false, + }, + }, + }) +} + func testCheckARMSimpleLBExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API @@ -378,3 +401,50 @@ resource "azurerm_simple_lb" "test" { } } ` + +const testAccAzureRMSimpleLB_dynamicFrontEndIPAddress = ` +resource "azurerm_resource_group" "test" { + name = "acctestlbrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestnet%d" + address_space = ["10.0.0.0/16"] + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.0.0/24" +} + +resource "azurerm_simple_lb" "test" { + name = "acctestlb%d" + location = "West US" + type = "Microsoft.Network/loadBalancers" + resource_group_name = "${azurerm_resource_group.test.name}" + frontend_subnet = "${azurerm_subnet.test.id}" + frontend_allocation_method = "Dynamic" + + probe { + name = "testProbe1" + protocol = "Tcp" + port = 22 + interval = 5 + number_of_probes = 16 + } + + rule { + protocol = "Tcp" + load_distribution = "Default" + frontend_port = 22 + backend_port = 22 + name = "rule1" + probe_name = "testProbe1" + } +} +` From c0478f269a3a682e926b743a835845cfecbb643f Mon Sep 17 00:00:00 2001 From: John Bresnahan Date: Tue, 12 Jul 2016 13:52:57 -0500 Subject: [PATCH 09/12] Patch the load balancer create to properly report the initial state --- builtin/providers/azurerm/resource_arm_simple_lb.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index beac4f160466..15a59edc34d6 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -260,9 +260,8 @@ func pullOutLbRules(d *schema.ResourceData, loadBalancer network.LoadBalancer) ( log.Printf("[resourceArmSimpleLb] pullOutLbRules found %d rules in plan", rules.Len()) for _, rule := range rules.List() { rule := rule.(map[string]interface{}) - log.Printf("[resourceArmSimpleLb] pullOutLbRules %v", rule) - ruleName := rule["name"].(string) + log.Printf("[resourceArmSimpleLb] pullOutLbRules %s", ruleName) existingRule, err := findRuleByName(loadBalancer.Properties.LoadBalancingRules, ruleName) if err == nil { @@ -438,6 +437,11 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { log.Printf("[resourceArmSimpleLb] ERROR When trying to set the rules. LB got status %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM creation request for load balancer '%s': %s", name, err) } + respLb, err = lbClient.Get(resGrp, name, "") + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR LB retrieving load balancer %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM get request for load balancer '%s': %s", name, err) + } return flattenAllOfLb(respLb, d, meta) } @@ -496,9 +500,11 @@ func flattenAzureRmLoadBalancerRules(loadBalancer network.LoadBalancer, d *schem ruleProbeID := *rule.Properties.Probe.ID conf, err := findProbeById(loadBalancer.Properties.Probes, ruleProbeID) if err != nil { + log.Printf("[resourceArmSimpleLb] Error reading %s", *rule.Name) return err } r["probe_name"] = *conf.Name + log.Printf("[resourceArmSimpleLb] Successfully read rule %s", *rule.Name) } ruleSet.Add(r) } From 68f49608de1a0c9990e43125740455f9b333a996 Mon Sep 17 00:00:00 2001 From: Peter McAtominey Date: Tue, 12 Jul 2016 18:19:01 +0100 Subject: [PATCH 10/12] provider/azurerm: lower case azurerm_simple_lb.frontend_allocation_method to prevent unnecessary recreations --- builtin/providers/azurerm/resource_arm_simple_lb.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index 15a59edc34d6..95096753df5c 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -70,6 +70,9 @@ func resourceArmSimpleLb() *schema.Resource { Required: true, ValidateFunc: validateAllocationMethod, ForceNew: true, + StateFunc: func(id interface{}) string { + return strings.ToLower(id.(string)) + }, }, "frontend_subnet": &schema.Schema{ Type: schema.TypeString, @@ -462,7 +465,7 @@ func flattenAzureRmFrontendIp(frontenIpArray []network.FrontendIPConfiguration, if frontenIp.Properties.PrivateIPAddress != nil { d.Set("frontend_private_ip_address", *frontenIp.Properties.PrivateIPAddress) } - d.Set("frontend_allocation_method", string(frontenIp.Properties.PrivateIPAllocationMethod)) + d.Set("frontend_allocation_method", strings.ToLower(string(frontenIp.Properties.PrivateIPAllocationMethod))) if frontenIp.Properties.Subnet != nil { d.Set("frontend_subnet", *frontenIp.Properties.Subnet.ID) } From 73dde85ed228376321f164432a6af5e4182d9a64 Mon Sep 17 00:00:00 2001 From: Peter McAtominey Date: Tue, 12 Jul 2016 22:04:00 +0100 Subject: [PATCH 11/12] providers/azurerm: clean up azurerm_simple_lb variable/function names brought test function names into line with the rest of the azurerm package fixed typos of frontend fixed variable casing --- .../azurerm/resource_arm_simple_lb.go | 66 +++++++++---------- .../azurerm/resource_arm_simple_lb_test.go | 50 +++++++------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index 95096753df5c..3c6181dcb887 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -332,40 +332,40 @@ func pullOutFrontEndIps(d *schema.ResourceData) (*[]network.FrontendIPConfigurat returnRules := []network.FrontendIPConfiguration{} - frontedIpName := fmt.Sprintf("%sfrontendip", d.Get("name").(string)) - frontedIpAllocationMethod := network.IPAllocationMethod(d.Get("frontend_allocation_method").(string)) - frontedIpSubnet := d.Get("frontend_subnet").(string) - frontedIpPublicIpAddress := d.Get("frontend_public_ip_address").(string) - frontedIpPrivateIpAddress := d.Get("frontend_private_ip_address").(string) + frontendIpName := fmt.Sprintf("%sfrontendip", d.Get("name").(string)) + frontendIpAllocationMethod := network.IPAllocationMethod(d.Get("frontend_allocation_method").(string)) + frontendIpSubnet := d.Get("frontend_subnet").(string) + frontendIpPublicIpAddress := d.Get("frontend_public_ip_address").(string) + frontendIpPrivateIpAddress := d.Get("frontend_private_ip_address").(string) - if frontedIpSubnet == "" && frontedIpPublicIpAddress == "" { + if frontendIpSubnet == "" && frontendIpPublicIpAddress == "" { var logMsg = fmt.Sprintf("[ERROR] Either a subnet of a public ip address must be provided") log.Printf("[resourceArmSimpleLb] %s", logMsg) return nil, fmt.Errorf(logMsg) } - if frontedIpPrivateIpAddress == "" && frontedIpAllocationMethod == network.Static { + if frontendIpPrivateIpAddress == "" && frontendIpAllocationMethod == network.Static { var logMsg = fmt.Sprintf("An private IP address must be provided if static allocation is used.") log.Printf("[resourceArmSimpleLb] %s", logMsg) return nil, fmt.Errorf(logMsg) } ipProps := network.FrontendIPConfigurationPropertiesFormat{ - PrivateIPAllocationMethod: frontedIpAllocationMethod} + PrivateIPAllocationMethod: frontendIpAllocationMethod} - if frontedIpSubnet != "" { - subnet := network.Subnet{ID: &frontedIpSubnet} + if frontendIpSubnet != "" { + subnet := network.Subnet{ID: &frontendIpSubnet} ipProps.Subnet = &subnet } - if frontedIpPublicIpAddress != "" { - pubIp := network.PublicIPAddress{ID: &frontedIpPublicIpAddress} + if frontendIpPublicIpAddress != "" { + pubIp := network.PublicIPAddress{ID: &frontendIpPublicIpAddress} ipProps.PublicIPAddress = &pubIp } - if frontedIpPrivateIpAddress != "" { - ipProps.PrivateIPAddress = &frontedIpPrivateIpAddress + if frontendIpPrivateIpAddress != "" { + ipProps.PrivateIPAddress = &frontendIpPrivateIpAddress } - frontendIpConf := network.FrontendIPConfiguration{Name: &frontedIpName, Properties: &ipProps} + frontendIpConf := network.FrontendIPConfiguration{Name: &frontendIpName, Properties: &ipProps} returnRules = append(returnRules, frontendIpConf) return &returnRules, nil } @@ -402,10 +402,10 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { } loadBalancer.Properties.Probes = probes - new_backend_pool_name := fmt.Sprintf("%sbackendpool", name) - backendpool := network.BackendAddressPool{Name: &new_backend_pool_name} + newBackendPoolName := fmt.Sprintf("%sbackendpool", name) + backendPool := network.BackendAddressPool{Name: &newBackendPoolName} backendPoolConfs := []network.BackendAddressPool{} - backendPoolConfs = append(backendPoolConfs, backendpool) + backendPoolConfs = append(backendPoolConfs, backendPool) loadBalancer.Properties.BackendAddressPools = &backendPoolConfs loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} @@ -449,28 +449,28 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { return flattenAllOfLb(respLb, d, meta) } -func flattenAzureRmFrontendIp(frontenIpArray []network.FrontendIPConfiguration, d *schema.ResourceData) error { +func flattenAzureRmFrontendIp(frontendIpArray []network.FrontendIPConfiguration, d *schema.ResourceData) error { log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[enter]") defer log.Printf("[resourceArmSimpleLb] flattenAzureRmFrontendIp[exit]") - if len(frontenIpArray) < 1 { + if len(frontendIpArray) < 1 { return nil } - if len(frontenIpArray) > 1 { + if len(frontendIpArray) > 1 { log.Printf("[WARN] More than 1 frontend ip was found. The simpleLB resource will just use the first one.") } - frontenIp := frontenIpArray[0] + frontendIp := frontendIpArray[0] - if frontenIp.Properties.PrivateIPAddress != nil { - d.Set("frontend_private_ip_address", *frontenIp.Properties.PrivateIPAddress) + if frontendIp.Properties.PrivateIPAddress != nil { + d.Set("frontend_private_ip_address", *frontendIp.Properties.PrivateIPAddress) } - d.Set("frontend_allocation_method", strings.ToLower(string(frontenIp.Properties.PrivateIPAllocationMethod))) - if frontenIp.Properties.Subnet != nil { - d.Set("frontend_subnet", *frontenIp.Properties.Subnet.ID) + d.Set("frontend_allocation_method", strings.ToLower(string(frontendIp.Properties.PrivateIPAllocationMethod))) + if frontendIp.Properties.Subnet != nil { + d.Set("frontend_subnet", *frontendIp.Properties.Subnet.ID) } - if frontenIp.Properties.PublicIPAddress != nil { - d.Set("frontend_public_ip_address", *frontenIp.Properties.PublicIPAddress.ID) + if frontendIp.Properties.PublicIPAddress != nil { + d.Set("frontend_public_ip_address", *frontendIp.Properties.PublicIPAddress.ID) } return nil @@ -570,10 +570,10 @@ func resourceArmSimpleLbUpdate(d *schema.ResourceData, meta interface{}) error { } loadBalancer.Properties.Probes = probes - new_backend_pool_name := fmt.Sprintf("%sbackendpool", name) - backendpool := network.BackendAddressPool{Name: &new_backend_pool_name} + newBackendPoolName := fmt.Sprintf("%sbackendpool", name) + backendPool := network.BackendAddressPool{Name: &newBackendPoolName} backendPoolConfs := []network.BackendAddressPool{} - backendPoolConfs = append(backendPoolConfs, backendpool) + backendPoolConfs = append(backendPoolConfs, backendPool) loadBalancer.Properties.BackendAddressPools = &backendPoolConfs loadBalancer.Properties.LoadBalancingRules = &[]network.LoadBalancingRule{} @@ -684,7 +684,7 @@ func flattenAllOfLb(loadBalancer network.LoadBalancer, d *schema.ResourceData, m } d.Set("backend_pool_id", (*loadBalancer.Properties.BackendAddressPools)[0].ID) if loadBalancer.Properties.FrontendIPConfigurations == nil || len(*loadBalancer.Properties.FrontendIPConfigurations) != 1 { - return fmt.Errorf("There must be exactly 1 fronted to use this resource") + return fmt.Errorf("There must be exactly 1 frontend to use this resource") } d.Set("frontend_id", (*loadBalancer.Properties.FrontendIPConfigurations)[0].ID) err = flattenAzureRmLoadBalancerRules(loadBalancer, d) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb_test.go b/builtin/providers/azurerm/resource_arm_simple_lb_test.go index 175caeae89c5..a35a0deda499 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb_test.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb_test.go @@ -12,22 +12,22 @@ import ( "github.com/hashicorp/terraform/terraform" ) -func TestAccARMSimpleLB_basic(t *testing.T) { +func TestAccAzureRMSimpleLB_basic(t *testing.T) { ri := acctest.RandInt() - config := fmt.Sprintf(testAccAzureSimpleLB_basic, ri, ri, ri) + config := fmt.Sprintf(testAccAzureRMSimpleLB_basic, ri, ri, ri) justBeThere := regexp.MustCompile(".*") resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testCheckARMSimpleRMLBDestroy, + CheckDestroy: testCheckAzureRMSimpleRMLBDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: config, Check: resource.ComposeTestCheckFunc( - testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), resource.TestMatchResourceAttr("azurerm_simple_lb.test", "frontend_id", justBeThere), resource.TestMatchResourceAttr("azurerm_simple_lb.test", "backend_pool_id", justBeThere), ), @@ -36,21 +36,21 @@ func TestAccARMSimpleLB_basic(t *testing.T) { }) } -func TestAccARMSimpleLB_updateTag(t *testing.T) { +func TestAccAzureRMSimpleLB_updateTag(t *testing.T) { ri := acctest.RandInt() - preConfig := fmt.Sprintf(testAccAzureSimpleLB_tags, ri, ri, ri) - postConfig := fmt.Sprintf(testAccAzureSimpleLB_updateTags, ri, ri, ri) + preConfig := fmt.Sprintf(testAccAzureRMSimpleLB_tags, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMSimpleLB_updateTags, ri, ri, ri) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testCheckARMSimpleRMLBDestroy, + CheckDestroy: testCheckAzureRMSimpleRMLBDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: preConfig, Check: resource.ComposeTestCheckFunc( - testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), resource.TestCheckResourceAttr( "azurerm_simple_lb.test", "tags.#", "2"), resource.TestCheckResourceAttr( @@ -63,7 +63,7 @@ func TestAccARMSimpleLB_updateTag(t *testing.T) { resource.TestStep{ Config: postConfig, Check: resource.ComposeTestCheckFunc( - testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), resource.TestCheckResourceAttr( "azurerm_simple_lb.test", "tags.#", "1"), resource.TestCheckResourceAttr( @@ -74,21 +74,21 @@ func TestAccARMSimpleLB_updateTag(t *testing.T) { }) } -func TestAccARMSimpleLB_updateProbe(t *testing.T) { +func TestAccAzureRMSimpleLB_updateProbe(t *testing.T) { ri := acctest.RandInt() - preConfig := fmt.Sprintf(testAccAzureSimpleLB_probe, ri, ri, ri) - postConfig := fmt.Sprintf(testAccAzureSimpleLB_probeUpdate, ri, ri, ri) + preConfig := fmt.Sprintf(testAccAzureRMSimpleLB_probe, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMSimpleLB_probeUpdate, ri, ri, ri) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testCheckARMSimpleRMLBDestroy, + CheckDestroy: testCheckAzureRMSimpleRMLBDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: preConfig, Check: resource.ComposeTestCheckFunc( - testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), resource.TestCheckResourceAttr( "azurerm_simple_lb.test", "probe.#", "2"), ), @@ -97,7 +97,7 @@ func TestAccARMSimpleLB_updateProbe(t *testing.T) { resource.TestStep{ Config: postConfig, Check: resource.ComposeTestCheckFunc( - testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), resource.TestCheckResourceAttr( "azurerm_simple_lb.test", "probe.#", "1"), ), @@ -113,11 +113,11 @@ func TestAccAzureRMSimpleLB_dynamicFrontEndIPAddress(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testCheckARMSimpleRMLBDestroy, + CheckDestroy: testCheckAzureRMSimpleRMLBDestroy, Steps: []resource.TestStep{ { Config: config, - Check: testCheckARMSimpleLBExists("azurerm_simple_lb.test"), + Check: testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), }, { Config: config, @@ -128,7 +128,7 @@ func TestAccAzureRMSimpleLB_dynamicFrontEndIPAddress(t *testing.T) { }) } -func testCheckARMSimpleLBExists(name string) resource.TestCheckFunc { +func testCheckAzureRMSimpleLBExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API rs, ok := s.RootModule().Resources[name] @@ -157,7 +157,7 @@ func testCheckARMSimpleLBExists(name string) resource.TestCheckFunc { } } -func testCheckARMSimpleRMLBDestroy(s *terraform.State) error { +func testCheckAzureRMSimpleRMLBDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*ArmClient).loadBalancerClient for _, rs := range s.RootModule().Resources { @@ -182,7 +182,7 @@ func testCheckARMSimpleRMLBDestroy(s *terraform.State) error { return nil } -var testAccAzureSimpleLB_basic = ` +var testAccAzureRMSimpleLB_basic = ` resource "azurerm_resource_group" "test" { name = "acctestlbrg-%d" location = "West US" @@ -221,7 +221,7 @@ resource "azurerm_simple_lb" "test" { } ` -var testAccAzureSimpleLB_tags = ` +var testAccAzureRMSimpleLB_tags = ` resource "azurerm_resource_group" "test" { name = "acctestlbrg-%d" location = "West US" @@ -265,7 +265,7 @@ resource "azurerm_simple_lb" "test" { } ` -var testAccAzureSimpleLB_updateTags = ` +var testAccAzureRMSimpleLB_updateTags = ` resource "azurerm_resource_group" "test" { name = "acctestlbrg-%d" location = "West US" @@ -308,7 +308,7 @@ resource "azurerm_simple_lb" "test" { } ` -var testAccAzureSimpleLB_probe = ` +var testAccAzureRMSimpleLB_probe = ` resource "azurerm_resource_group" "test" { name = "acctestlbrg-%d" location = "West US" @@ -363,7 +363,7 @@ resource "azurerm_simple_lb" "test" { } ` -var testAccAzureSimpleLB_probeUpdate = ` +var testAccAzureRMSimpleLB_probeUpdate = ` resource "azurerm_resource_group" "test" { name = "acctestlbrg-%d" location = "West US" From 0660a306e879a337d1414a25333b88a878261490 Mon Sep 17 00:00:00 2001 From: John Bresnahan Date: Tue, 12 Jul 2016 18:52:28 -0500 Subject: [PATCH 12/12] Updating the simple_lb tags test from # to % --- builtin/providers/azurerm/resource_arm_simple_lb.go | 10 ++++++++-- .../providers/azurerm/resource_arm_simple_lb_test.go | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_simple_lb.go b/builtin/providers/azurerm/resource_arm_simple_lb.go index 3c6181dcb887..fb15fd3142a6 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb.go @@ -445,7 +445,7 @@ func resourceArmSimpleLbCreate(d *schema.ResourceData, meta interface{}) error { log.Printf("[resourceArmSimpleLb] ERROR LB retrieving load balancer %s", err.Error()) return fmt.Errorf("Error issuing Azure ARM get request for load balancer '%s': %s", name, err) } - + log.Printf("XXXXXX 2 %s", respLb.Tags) return flattenAllOfLb(respLb, d, meta) } @@ -610,6 +610,12 @@ func resourceArmSimpleLbUpdate(d *schema.ResourceData, meta interface{}) error { } log.Printf("[resourceArmSimpleLb] Set the rules on the LB. Provision State %s", *respLb.Properties.ProvisioningState) + respLb, err = lbClient.Get(resGrp, name, "") + if err != nil { + log.Printf("[resourceArmSimpleLb] ERROR LB retrieving load balancer %s", err.Error()) + return fmt.Errorf("Error issuing Azure ARM get request for load balancer '%s': %s", name, err) + } + log.Printf("XXXXXX 3 %s", respLb.Tags) return flattenAllOfLb(respLb, d, meta) } @@ -655,7 +661,7 @@ func resourceArmSimpleLbRead(d *schema.ResourceData, meta interface{}) error { } return fmt.Errorf("Error reading the state of the load balancer off Azure: %s", err) } - + log.Printf("XXXXXX 1 %s", loadBalancer.Tags) return flattenAllOfLb(loadBalancer, d, meta) } diff --git a/builtin/providers/azurerm/resource_arm_simple_lb_test.go b/builtin/providers/azurerm/resource_arm_simple_lb_test.go index a35a0deda499..123b5f829517 100644 --- a/builtin/providers/azurerm/resource_arm_simple_lb_test.go +++ b/builtin/providers/azurerm/resource_arm_simple_lb_test.go @@ -52,7 +52,7 @@ func TestAccAzureRMSimpleLB_updateTag(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), resource.TestCheckResourceAttr( - "azurerm_simple_lb.test", "tags.#", "2"), + "azurerm_simple_lb.test", "tags.%", "2"), resource.TestCheckResourceAttr( "azurerm_simple_lb.test", "tags.environment", "Production"), resource.TestCheckResourceAttr( @@ -65,7 +65,7 @@ func TestAccAzureRMSimpleLB_updateTag(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMSimpleLBExists("azurerm_simple_lb.test"), resource.TestCheckResourceAttr( - "azurerm_simple_lb.test", "tags.#", "1"), + "azurerm_simple_lb.test", "tags.%", "1"), resource.TestCheckResourceAttr( "azurerm_simple_lb.test", "tags.environment", "staging"), ),