provider/azurerm: Add Load Balancer resources (#9199)

* provider/azurerm: Add AzureRM Loadbalancer resource

Adds support for the elusive Azure LoadBalancer

* [x] `azurerm_lb`
* [x] `azurerm_lb_backend_address_pool`
* [x] `azurerm_lb_rule`
* [x] `azurerm_lb_nat_rule`
* [x] `azurerm_lb_probe`
* [x] `azurerm_lb_nat_pool`

Test Results:

```
make testacc TEST=./builtin/providers/azurerm TESTARGS='-run=TestAccAzureRMLoadbalancer'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
TF_ACC=1 go test ./builtin/providers/azurerm -v
-run=TestAccAzureRMLoadbalancer -timeout 120m
=== RUN   TestAccAzureRMLoadbalancerBackEndAddressPool_basic
--- PASS: TestAccAzureRMLoadbalancerBackEndAddressPool_basic (207.26s)
=== RUN   TestAccAzureRMLoadbalancerBackEndAddressPool_removal
--- PASS: TestAccAzureRMLoadbalancerBackEndAddressPool_removal (165.89s)
=== RUN   TestAccAzureRMLoadbalancerNatRule_basic
--- PASS: TestAccAzureRMLoadbalancerNatRule_basic (179.30s)
=== RUN   TestAccAzureRMLoadbalancerNatRule_removal
--- PASS: TestAccAzureRMLoadbalancerNatRule_removal (180.73s)
=== RUN   TestAccAzureRMLoadbalancerRule_basic
--- PASS: TestAccAzureRMLoadbalancerRule_basic (170.40s)
=== RUN   TestAccAzureRMLoadbalancerRule_removal
--- PASS: TestAccAzureRMLoadbalancerRule_removal (204.23s)
=== RUN   TestAccAzureRMLoadbalancer_basic
--- PASS: TestAccAzureRMLoadbalancer_basic (136.03s)
=== RUN   TestAccAzureRMLoadbalancer_frontEndConfig
--- PASS: TestAccAzureRMLoadbalancer_frontEndConfig (214.47s)
=== RUN   TestAccAzureRMLoadbalancer_tags
--- PASS: TestAccAzureRMLoadbalancer_tags (215.52s)
=== RUN   TestAccAzureRMLoadbalancerProbe_basic
--- PASS: TestAccAzureRMLoadbalancerProbe_basic (183.36s)
=== RUN   TestAccAzureRMLoadbalancerProbe_removal
--- PASS: TestAccAzureRMLoadbalancerProbe_removal (185.86s)
=== RUN   TestAccAzureRMLoadbalancerNatPool_basic
--- PASS: TestAccAzureRMLoadbalancerNatPool_basic (161.47s)
=== RUN   TestAccAzureRMLoadbalancerNatPool_removal
--- PASS: TestAccAzureRMLoadbalancerNatPool_removal (167.38s)
PASS
ok      github.com/hashicorp/terraform/builtin/providers/azurerm
1673.852s
```

* provider/azurerm: Documentation for the ARM LB resources
This commit is contained in:
Paul Stack 2016-10-07 19:14:26 +01:00 committed by James Nugent
parent 42c2fe5c85
commit a085c8d71e
22 changed files with 3220 additions and 3 deletions

View File

@ -0,0 +1,144 @@
package azurerm
import (
"fmt"
"net/http"
"strings"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
)
func resourceGroupAndLBNameFromId(loadBalancerId string) (string, string, error) {
id, err := parseAzureResourceID(loadBalancerId)
if err != nil {
return "", "", err
}
name := id.Path["loadBalancers"]
resGroup := id.ResourceGroup
return resGroup, name, nil
}
func retrieveLoadBalancerById(loadBalancerId string, meta interface{}) (*network.LoadBalancer, bool, error) {
loadBalancerClient := meta.(*ArmClient).loadBalancerClient
resGroup, name, err := resourceGroupAndLBNameFromId(loadBalancerId)
if err != nil {
return nil, false, errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
resp, err := loadBalancerClient.Get(resGroup, name, "")
if err != nil {
if resp.StatusCode == http.StatusNotFound {
return nil, false, nil
}
return nil, false, fmt.Errorf("Error making Read request on Azure LoadBalancer %s: %s", name, err)
}
return &resp, true, nil
}
func findLoadBalancerBackEndAddressPoolByName(lb *network.LoadBalancer, name string) (*network.BackendAddressPool, int, bool) {
if lb == nil || lb.Properties == nil || lb.Properties.BackendAddressPools == nil {
return nil, -1, false
}
for i, apc := range *lb.Properties.BackendAddressPools {
if apc.Name != nil && *apc.Name == name {
return &apc, i, true
}
}
return nil, -1, false
}
func findLoadBalancerFrontEndIpConfigurationByName(lb *network.LoadBalancer, name string) (*network.FrontendIPConfiguration, int, bool) {
if lb == nil || lb.Properties == nil || lb.Properties.FrontendIPConfigurations == nil {
return nil, -1, false
}
for i, feip := range *lb.Properties.FrontendIPConfigurations {
if feip.Name != nil && *feip.Name == name {
return &feip, i, true
}
}
return nil, -1, false
}
func findLoadBalancerRuleByName(lb *network.LoadBalancer, name string) (*network.LoadBalancingRule, int, bool) {
if lb == nil || lb.Properties == nil || lb.Properties.LoadBalancingRules == nil {
return nil, -1, false
}
for i, lbr := range *lb.Properties.LoadBalancingRules {
if lbr.Name != nil && *lbr.Name == name {
return &lbr, i, true
}
}
return nil, -1, false
}
func findLoadBalancerNatRuleByName(lb *network.LoadBalancer, name string) (*network.InboundNatRule, int, bool) {
if lb == nil || lb.Properties == nil || lb.Properties.InboundNatRules == nil {
return nil, -1, false
}
for i, nr := range *lb.Properties.InboundNatRules {
if nr.Name != nil && *nr.Name == name {
return &nr, i, true
}
}
return nil, -1, false
}
func findLoadBalancerNatPoolByName(lb *network.LoadBalancer, name string) (*network.InboundNatPool, int, bool) {
if lb == nil || lb.Properties == nil || lb.Properties.InboundNatPools == nil {
return nil, -1, false
}
for i, np := range *lb.Properties.InboundNatPools {
if np.Name != nil && *np.Name == name {
return &np, i, true
}
}
return nil, -1, false
}
func findLoadBalancerProbeByName(lb *network.LoadBalancer, name string) (*network.Probe, int, bool) {
if lb == nil || lb.Properties == nil || lb.Properties.Probes == nil {
return nil, -1, false
}
for i, p := range *lb.Properties.Probes {
if p.Name != nil && *p.Name == name {
return &p, i, true
}
}
return nil, -1, false
}
func loadbalancerStateRefreshFunc(client *ArmClient, resourceGroupName string, loadbalancer string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
res, err := client.loadBalancerClient.Get(resourceGroupName, loadbalancer, "")
if err != nil {
return nil, "", fmt.Errorf("Error issuing read request in loadbalancerStateRefreshFunc to Azure ARM for LoadBalancer '%s' (RG: '%s'): %s", loadbalancer, resourceGroupName, err)
}
return res, *res.Properties.ProvisioningState, nil
}
}
func validateLoadBalancerPrivateIpAddressAllocation(v interface{}, k string) (ws []string, errors []error) {
value := strings.ToLower(v.(string))
if value != "static" && value != "dynamic" {
errors = append(errors, fmt.Errorf("LoadBalancer Allocations can only be Static or Dynamic"))
}
return
}

View File

@ -46,9 +46,17 @@ func Provider() terraform.ResourceProvider {
ResourcesMap: map[string]*schema.Resource{
// These resources use the Azure ARM SDK
"azurerm_availability_set": resourceArmAvailabilitySet(),
"azurerm_cdn_endpoint": resourceArmCdnEndpoint(),
"azurerm_cdn_profile": resourceArmCdnProfile(),
"azurerm_availability_set": resourceArmAvailabilitySet(),
"azurerm_cdn_endpoint": resourceArmCdnEndpoint(),
"azurerm_cdn_profile": resourceArmCdnProfile(),
"azurerm_lb": resourceArmLoadBalancer(),
"azurerm_lb_backend_address_pool": resourceArmLoadBalancerBackendAddressPool(),
"azurerm_lb_nat_rule": resourceArmLoadBalancerNatRule(),
"azurerm_lb_nat_pool": resourceArmLoadBalancerNatPool(),
"azurerm_lb_probe": resourceArmLoadBalancerProbe(),
"azurerm_lb_rule": resourceArmLoadBalancerRule(),
"azurerm_local_network_gateway": resourceArmLocalNetworkGateway(),
"azurerm_network_interface": resourceArmNetworkInterface(),
"azurerm_network_security_group": resourceArmNetworkSecurityGroup(),

View File

@ -0,0 +1,275 @@
package azurerm
import (
"fmt"
"log"
"time"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/jen20/riviera/azure"
)
func resourceArmLoadBalancer() *schema.Resource {
return &schema.Resource{
Create: resourceArmLoadBalancerCreate,
Read: resourecArmLoadBalancerRead,
Update: resourceArmLoadBalancerCreate,
Delete: resourceArmLoadBalancerDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: azureRMNormalizeLocation,
},
"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"frontend_ip_configuration": {
Type: schema.TypeList,
Optional: true,
MinItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"subnet_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"private_ip_address": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"public_ip_address_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"private_ip_address_allocation": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validateLoadBalancerPrivateIpAddressAllocation,
},
"load_balancer_rules": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"inbound_nat_rules": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
},
},
"tags": tagsSchema(),
},
}
}
func resourceArmLoadBalancerCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
loadBalancerClient := client.loadBalancerClient
log.Printf("[INFO] preparing arguments for Azure ARM LoadBalancer creation.")
name := d.Get("name").(string)
location := d.Get("location").(string)
resGroup := d.Get("resource_group_name").(string)
tags := d.Get("tags").(map[string]interface{})
expandedTags := expandTags(tags)
properties := network.LoadBalancerPropertiesFormat{}
if _, ok := d.GetOk("frontend_ip_configuration"); ok {
properties.FrontendIPConfigurations = expandAzureRmLoadBalancerFrontendIpConfigurations(d)
}
loadbalancer := network.LoadBalancer{
Name: azure.String(name),
Location: azure.String(location),
Tags: expandedTags,
Properties: &properties,
}
_, err := loadBalancerClient.CreateOrUpdate(resGroup, name, loadbalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := loadBalancerClient.Get(resGroup, name, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", name, resGroup)
}
d.SetId(*read.ID)
log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", name)
stateConf := &resource.StateChangeConf{
Pending: []string{"Accepted", "Updating"},
Target: []string{"Succeeded"},
Refresh: loadbalancerStateRefreshFunc(client, resGroup, name),
Timeout: 10 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", name, err)
}
return resourecArmLoadBalancerRead(d, meta)
}
func resourecArmLoadBalancerRead(d *schema.ResourceData, meta interface{}) error {
loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
if loadBalancer.Properties != nil && loadBalancer.Properties.FrontendIPConfigurations != nil {
d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(loadBalancer.Properties.FrontendIPConfigurations))
}
flattenAndSetTags(d, loadBalancer.Tags)
return nil
}
func resourceArmLoadBalancerDelete(d *schema.ResourceData, meta interface{}) error {
loadBalancerClient := meta.(*ArmClient).loadBalancerClient
id, err := parseAzureResourceID(d.Id())
if err != nil {
return errwrap.Wrapf("Error Parsing Azure Resource ID {{err}}", err)
}
resGroup := id.ResourceGroup
name := id.Path["loadBalancers"]
_, err = loadBalancerClient.Delete(resGroup, name, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Deleting LoadBalancer {{err}}", err)
}
d.SetId("")
return nil
}
func expandAzureRmLoadBalancerFrontendIpConfigurations(d *schema.ResourceData) *[]network.FrontendIPConfiguration {
configs := d.Get("frontend_ip_configuration").([]interface{})
frontEndConfigs := make([]network.FrontendIPConfiguration, 0, len(configs))
for _, configRaw := range configs {
data := configRaw.(map[string]interface{})
private_ip_allocation_method := data["private_ip_address_allocation"].(string)
properties := network.FrontendIPConfigurationPropertiesFormat{
PrivateIPAllocationMethod: network.IPAllocationMethod(private_ip_allocation_method),
}
if v := data["private_ip_address"].(string); v != "" {
properties.PrivateIPAddress = &v
}
if v := data["public_ip_address_id"].(string); v != "" {
properties.PublicIPAddress = &network.PublicIPAddress{
ID: &v,
}
}
if v := data["subnet_id"].(string); v != "" {
properties.Subnet = &network.Subnet{
ID: &v,
}
}
name := data["name"].(string)
frontEndConfig := network.FrontendIPConfiguration{
Name: &name,
Properties: &properties,
}
frontEndConfigs = append(frontEndConfigs, frontEndConfig)
}
return &frontEndConfigs
}
func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPConfiguration) []interface{} {
result := make([]interface{}, 0, len(*ipConfigs))
for _, config := range *ipConfigs {
ipConfig := make(map[string]interface{})
ipConfig["name"] = *config.Name
ipConfig["private_ip_address_allocation"] = config.Properties.PrivateIPAllocationMethod
if config.Properties.Subnet != nil {
ipConfig["subnet_id"] = *config.Properties.Subnet.ID
}
if config.Properties.PrivateIPAddress != nil {
ipConfig["private_ip_address"] = *config.Properties.PrivateIPAddress
}
if config.Properties.PublicIPAddress != nil {
ipConfig["public_ip_address_id"] = *config.Properties.PublicIPAddress.ID
}
if config.Properties.LoadBalancingRules != nil {
load_balancing_rules := make([]string, 0, len(*config.Properties.LoadBalancingRules))
for _, rule := range *config.Properties.LoadBalancingRules {
load_balancing_rules = append(load_balancing_rules, *rule.ID)
}
ipConfig["load_balancer_rules"] = load_balancing_rules
}
if config.Properties.InboundNatRules != nil {
inbound_nat_rules := make([]string, 0, len(*config.Properties.InboundNatRules))
for _, rule := range *config.Properties.InboundNatRules {
inbound_nat_rules = append(inbound_nat_rules, *rule.ID)
}
ipConfig["inbound_nat_rules"] = inbound_nat_rules
}
result = append(result, ipConfig)
}
return result
}

View File

@ -0,0 +1,207 @@
package azurerm
import (
"fmt"
"log"
"time"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/jen20/riviera/azure"
)
func resourceArmLoadBalancerBackendAddressPool() *schema.Resource {
return &schema.Resource{
Create: resourceArmLoadBalancerBackendAddressPoolCreate,
Read: resourceArmLoadBalancerBackendAddressPoolRead,
Delete: resourceArmLoadBalancerBackendAddressPoolDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: azureRMNormalizeLocation,
},
"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"loadbalancer_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"backend_ip_configurations": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"load_balancing_rules": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}
func resourceArmLoadBalancerBackendAddressPoolCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
_, _, exists = findLoadBalancerBackEndAddressPoolByName(loadBalancer, d.Get("name").(string))
if exists {
return fmt.Errorf("A BackEnd Address Pool with name %q already exists.", d.Get("name").(string))
}
backendAddressPools := append(*loadBalancer.Properties.BackendAddressPools, expandAzureRmLoadBalancerBackendAddressPools(d))
loadBalancer.Properties.BackendAddressPools = &backendAddressPools
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
d.SetId(*read.ID)
log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", loadBalancerName)
stateConf := &resource.StateChangeConf{
Pending: []string{"Accepted", "Updating"},
Target: []string{"Succeeded"},
Refresh: loadbalancerStateRefreshFunc(client, resGroup, loadBalancerName),
Timeout: 10 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", loadBalancerName, err)
}
return resourceArmLoadBalancerBackendAddressPoolRead(d, meta)
}
func resourceArmLoadBalancerBackendAddressPoolRead(d *schema.ResourceData, meta interface{}) error {
loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
configs := *loadBalancer.Properties.BackendAddressPools
for _, config := range configs {
if *config.Name == d.Get("name").(string) {
d.Set("name", config.Name)
if config.Properties.BackendIPConfigurations != nil {
backend_ip_configurations := make([]string, 0, len(*config.Properties.BackendIPConfigurations))
for _, backendConfig := range *config.Properties.BackendIPConfigurations {
backend_ip_configurations = append(backend_ip_configurations, *backendConfig.ID)
}
d.Set("backend_ip_configurations", backend_ip_configurations)
}
if config.Properties.LoadBalancingRules != nil {
load_balancing_rules := make([]string, 0, len(*config.Properties.LoadBalancingRules))
for _, rule := range *config.Properties.LoadBalancingRules {
load_balancing_rules = append(load_balancing_rules, *rule.ID)
}
d.Set("backend_ip_configurations", load_balancing_rules)
}
break
}
}
return nil
}
func resourceArmLoadBalancerBackendAddressPoolDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
return nil
}
_, index, exists := findLoadBalancerBackEndAddressPoolByName(loadBalancer, d.Get("name").(string))
if !exists {
return nil
}
oldBackEndPools := *loadBalancer.Properties.BackendAddressPools
newBackEndPools := append(oldBackEndPools[:index], oldBackEndPools[index+1:]...)
loadBalancer.Properties.BackendAddressPools = &newBackEndPools
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
return nil
}
func expandAzureRmLoadBalancerBackendAddressPools(d *schema.ResourceData) network.BackendAddressPool {
return network.BackendAddressPool{
Name: azure.String(d.Get("name").(string)),
}
}

View File

@ -0,0 +1,137 @@
package azurerm
import (
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAzureRMLoadBalancerBackEndAddressPool_basic(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
addressPoolName := fmt.Sprintf("%d-address-pool", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerBackEndAddressPool_basic(ri, addressPoolName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerBackEndAddressPoolExists(addressPoolName, &lb),
),
},
},
})
}
func TestAccAzureRMLoadBalancerBackEndAddressPool_removal(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
addressPoolName := fmt.Sprintf("%d-address-pool", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerBackEndAddressPool_removal(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerBackEndAddressPoolNotExists(addressPoolName, &lb),
),
},
},
})
}
func testCheckAzureRMLoadBalancerBackEndAddressPoolExists(addressPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerBackEndAddressPoolByName(lb, addressPoolName)
if !exists {
return fmt.Errorf("A BackEnd Address Pool with name %q cannot be found.", addressPoolName)
}
return nil
}
}
func testCheckAzureRMLoadBalancerBackEndAddressPoolNotExists(addressPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerBackEndAddressPoolByName(lb, addressPoolName)
if exists {
return fmt.Errorf("A BackEnd Address Pool with name %q has been found.", addressPoolName)
}
return nil
}
}
func testAccAzureRMLoadBalancerBackEndAddressPool_basic(rInt int, addressPoolName string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_backend_address_pool" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "%s"
}
`, rInt, rInt, rInt, rInt, addressPoolName)
}
func testAccAzureRMLoadBalancerBackEndAddressPool_removal(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
`, rInt, rInt, rInt, rInt)
}

View File

@ -0,0 +1,244 @@
package azurerm
import (
"fmt"
"log"
"time"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/jen20/riviera/azure"
)
func resourceArmLoadBalancerNatPool() *schema.Resource {
return &schema.Resource{
Create: resourceArmLoadBalancerNatPoolCreate,
Read: resourceArmLoadBalancerNatPoolRead,
Update: resourceArmLoadBalancerNatPoolCreate,
Delete: resourceArmLoadBalancerNatPoolDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: azureRMNormalizeLocation,
},
"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"loadbalancer_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"protocol": {
Type: schema.TypeString,
Required: true,
},
"frontend_port_start": {
Type: schema.TypeInt,
Required: true,
},
"frontend_port_end": {
Type: schema.TypeInt,
Required: true,
},
"backend_port": {
Type: schema.TypeInt,
Required: true,
},
"frontend_ip_configuration_name": {
Type: schema.TypeString,
Required: true,
},
"frontend_ip_configuration_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceArmLoadBalancerNatPoolCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
_, _, exists = findLoadBalancerNatPoolByName(loadBalancer, d.Get("name").(string))
if exists {
return fmt.Errorf("A NAT Pool with name %q already exists.", d.Get("name").(string))
}
newNatPool, err := expandAzureRmLoadBalancerNatPool(d, loadBalancer)
if err != nil {
return errwrap.Wrapf("Error Expanding NAT Pool {{err}}", err)
}
natPools := append(*loadBalancer.Properties.InboundNatPools, *newNatPool)
loadBalancer.Properties.InboundNatPools = &natPools
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
d.SetId(*read.ID)
log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", loadBalancerName)
stateConf := &resource.StateChangeConf{
Pending: []string{"Accepted", "Updating"},
Target: []string{"Succeeded"},
Refresh: loadbalancerStateRefreshFunc(client, resGroup, loadBalancerName),
Timeout: 10 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", loadBalancerName, err)
}
return resourceArmLoadBalancerNatPoolRead(d, meta)
}
func resourceArmLoadBalancerNatPoolRead(d *schema.ResourceData, meta interface{}) error {
loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
configs := *loadBalancer.Properties.InboundNatPools
for _, config := range configs {
if *config.Name == d.Get("name").(string) {
d.Set("name", config.Name)
d.Set("protocol", config.Properties.Protocol)
d.Set("frontend_port_start", config.Properties.FrontendPortRangeStart)
d.Set("frontend_port_end", config.Properties.FrontendPortRangeEnd)
d.Set("backend_port", config.Properties.BackendPort)
if config.Properties.FrontendIPConfiguration != nil {
d.Set("frontend_ip_configuration_id", config.Properties.FrontendIPConfiguration.ID)
}
break
}
}
return nil
}
func resourceArmLoadBalancerNatPoolDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
return nil
}
_, index, exists := findLoadBalancerNatPoolByName(loadBalancer, d.Get("name").(string))
if !exists {
return nil
}
oldNatPools := *loadBalancer.Properties.InboundNatPools
newNatPools := append(oldNatPools[:index], oldNatPools[index+1:]...)
loadBalancer.Properties.InboundNatPools = &newNatPools
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
return nil
}
func expandAzureRmLoadBalancerNatPool(d *schema.ResourceData, lb *network.LoadBalancer) (*network.InboundNatPool, error) {
properties := network.InboundNatPoolPropertiesFormat{
Protocol: network.TransportProtocol(d.Get("protocol").(string)),
FrontendPortRangeStart: azure.Int32(int32(d.Get("frontend_port_start").(int))),
FrontendPortRangeEnd: azure.Int32(int32(d.Get("frontend_port_end").(int))),
BackendPort: azure.Int32(int32(d.Get("backend_port").(int))),
}
if v := d.Get("frontend_ip_configuration_name").(string); v != "" {
rule, _, exists := findLoadBalancerFrontEndIpConfigurationByName(lb, v)
if !exists {
return nil, fmt.Errorf("[ERROR] Cannot find FrontEnd IP Configuration with the name %s", v)
}
feip := network.SubResource{
ID: rule.ID,
}
properties.FrontendIPConfiguration = &feip
}
natPool := network.InboundNatPool{
Name: azure.String(d.Get("name").(string)),
Properties: &properties,
}
return &natPool, nil
}

View File

@ -0,0 +1,149 @@
package azurerm
import (
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAzureRMLoadBalancerNatPool_basic(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
natPoolName := fmt.Sprintf("NatPool-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerNatPool_basic(ri, natPoolName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerNatPoolExists(natPoolName, &lb),
),
},
},
})
}
func TestAccAzureRMLoadBalancerNatPool_removal(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
natPoolName := fmt.Sprintf("NatPool-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerNatPool_basic(ri, natPoolName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerNatPoolExists(natPoolName, &lb),
),
},
{
Config: testAccAzureRMLoadBalancerNatPool_removal(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerNatPoolNotExists(natPoolName, &lb),
),
},
},
})
}
func testCheckAzureRMLoadBalancerNatPoolExists(natPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerNatPoolByName(lb, natPoolName)
if !exists {
return fmt.Errorf("A NAT Pool with name %q cannot be found.", natPoolName)
}
return nil
}
}
func testCheckAzureRMLoadBalancerNatPoolNotExists(natPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerNatPoolByName(lb, natPoolName)
if exists {
return fmt.Errorf("A NAT Pool with name %q has been found.", natPoolName)
}
return nil
}
}
func testAccAzureRMLoadBalancerNatPool_basic(rInt int, natPoolName string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_nat_pool" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "%s"
protocol = "Tcp"
frontend_port_start = 80
frontend_port_end = 81
backend_port = 3389
frontend_ip_configuration_name = "one-%d"
}
`, rInt, rInt, rInt, rInt, natPoolName, rInt)
}
func testAccAzureRMLoadBalancerNatPool_removal(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
`, rInt, rInt, rInt, rInt)
}

View File

@ -0,0 +1,246 @@
package azurerm
import (
"fmt"
"log"
"time"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/jen20/riviera/azure"
)
func resourceArmLoadBalancerNatRule() *schema.Resource {
return &schema.Resource{
Create: resourceArmLoadBalancerNatRuleCreate,
Read: resourceArmLoadBalancerNatRuleRead,
Update: resourceArmLoadBalancerNatRuleCreate,
Delete: resourceArmLoadBalancerNatRuleDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: azureRMNormalizeLocation,
},
"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"loadbalancer_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"protocol": {
Type: schema.TypeString,
Required: true,
},
"frontend_port": {
Type: schema.TypeInt,
Required: true,
},
"backend_port": {
Type: schema.TypeInt,
Required: true,
},
"frontend_ip_configuration_name": {
Type: schema.TypeString,
Required: true,
},
"frontend_ip_configuration_id": {
Type: schema.TypeString,
Computed: true,
},
"backend_ip_configuration_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceArmLoadBalancerNatRuleCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
_, _, exists = findLoadBalancerNatRuleByName(loadBalancer, d.Get("name").(string))
if exists {
return fmt.Errorf("A NAT Rule with name %q already exists.", d.Get("name").(string))
}
newNatRule, err := expandAzureRmLoadBalancerNatRule(d, loadBalancer)
if err != nil {
return errwrap.Wrapf("Error Expanding NAT Rule {{err}}", err)
}
natRules := append(*loadBalancer.Properties.InboundNatRules, *newNatRule)
loadBalancer.Properties.InboundNatRules = &natRules
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating / Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
d.SetId(*read.ID)
log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", loadBalancerName)
stateConf := &resource.StateChangeConf{
Pending: []string{"Accepted", "Updating"},
Target: []string{"Succeeded"},
Refresh: loadbalancerStateRefreshFunc(client, resGroup, loadBalancerName),
Timeout: 10 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", loadBalancerName, err)
}
return resourceArmLoadBalancerNatRuleRead(d, meta)
}
func resourceArmLoadBalancerNatRuleRead(d *schema.ResourceData, meta interface{}) error {
loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
configs := *loadBalancer.Properties.InboundNatRules
for _, config := range configs {
if *config.Name == d.Get("name").(string) {
d.Set("name", config.Name)
d.Set("protocol", config.Properties.Protocol)
d.Set("frontend_port", config.Properties.FrontendPort)
d.Set("backend_port", config.Properties.BackendPort)
if config.Properties.FrontendIPConfiguration != nil {
d.Set("frontend_ip_configuration_id", config.Properties.FrontendIPConfiguration.ID)
}
if config.Properties.BackendIPConfiguration != nil {
d.Set("backend_ip_configuration_id", config.Properties.BackendIPConfiguration.ID)
}
break
}
}
return nil
}
func resourceArmLoadBalancerNatRuleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
return nil
}
_, index, exists := findLoadBalancerNatRuleByName(loadBalancer, d.Get("name").(string))
if !exists {
return nil
}
oldNatRules := *loadBalancer.Properties.InboundNatRules
newNatRules := append(oldNatRules[:index], oldNatRules[index+1:]...)
loadBalancer.Properties.InboundNatRules = &newNatRules
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
return nil
}
func expandAzureRmLoadBalancerNatRule(d *schema.ResourceData, lb *network.LoadBalancer) (*network.InboundNatRule, error) {
properties := network.InboundNatRulePropertiesFormat{
Protocol: network.TransportProtocol(d.Get("protocol").(string)),
FrontendPort: azure.Int32(int32(d.Get("frontend_port").(int))),
BackendPort: azure.Int32(int32(d.Get("backend_port").(int))),
}
if v := d.Get("frontend_ip_configuration_name").(string); v != "" {
rule, _, exists := findLoadBalancerFrontEndIpConfigurationByName(lb, v)
if !exists {
return nil, fmt.Errorf("[ERROR] Cannot find FrontEnd IP Configuration with the name %s", v)
}
feip := network.SubResource{
ID: rule.ID,
}
properties.FrontendIPConfiguration = &feip
}
natRule := network.InboundNatRule{
Name: azure.String(d.Get("name").(string)),
Properties: &properties,
}
return &natRule, nil
}

View File

@ -0,0 +1,148 @@
package azurerm
import (
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAzureRMLoadBalancerNatRule_basic(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
natRuleName := fmt.Sprintf("NatRule-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerNatRule_basic(ri, natRuleName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerNatRuleExists(natRuleName, &lb),
),
},
},
})
}
func TestAccAzureRMLoadBalancerNatRule_removal(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
natRuleName := fmt.Sprintf("NatRule-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerNatRule_basic(ri, natRuleName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerNatRuleExists(natRuleName, &lb),
),
},
{
Config: testAccAzureRMLoadBalancerNatRule_removal(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerNatRuleNotExists(natRuleName, &lb),
),
},
},
})
}
func testCheckAzureRMLoadBalancerNatRuleExists(natRuleName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerNatRuleByName(lb, natRuleName)
if !exists {
return fmt.Errorf("A NAT Rule with name %q cannot be found.", natRuleName)
}
return nil
}
}
func testCheckAzureRMLoadBalancerNatRuleNotExists(natRuleName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerNatRuleByName(lb, natRuleName)
if exists {
return fmt.Errorf("A NAT Rule with name %q has been found.", natRuleName)
}
return nil
}
}
func testAccAzureRMLoadBalancerNatRule_basic(rInt int, natRuleName string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_nat_rule" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "%s"
protocol = "Tcp"
frontend_port = 3389
backend_port = 3389
frontend_ip_configuration_name = "one-%d"
}
`, rInt, rInt, rInt, rInt, natRuleName, rInt)
}
func testAccAzureRMLoadBalancerNatRule_removal(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
`, rInt, rInt, rInt, rInt)
}

View File

@ -0,0 +1,241 @@
package azurerm
import (
"fmt"
"log"
"time"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/jen20/riviera/azure"
)
func resourceArmLoadBalancerProbe() *schema.Resource {
return &schema.Resource{
Create: resourceArmLoadBalancerProbeCreate,
Read: resourceArmLoadBalancerProbeRead,
Update: resourceArmLoadBalancerProbeCreate,
Delete: resourceArmLoadBalancerProbeDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: azureRMNormalizeLocation,
},
"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"loadbalancer_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"protocol": {
Type: schema.TypeString,
Computed: true,
Optional: true,
},
"port": {
Type: schema.TypeInt,
Required: true,
},
"request_path": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"interval_in_seconds": {
Type: schema.TypeInt,
Optional: true,
Default: 15,
},
"number_of_probes": {
Type: schema.TypeInt,
Optional: true,
Default: 2,
},
"load_balance_rules": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}
func resourceArmLoadBalancerProbeCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
_, _, exists = findLoadBalancerProbeByName(loadBalancer, d.Get("name").(string))
if exists {
return fmt.Errorf("A Probe with name %q already exists.", d.Get("name").(string))
}
newProbe, err := expandAzureRmLoadBalancerProbe(d, loadBalancer)
if err != nil {
return errwrap.Wrapf("Error Expanding Probe {{err}}", err)
}
probes := append(*loadBalancer.Properties.Probes, *newProbe)
loadBalancer.Properties.Probes = &probes
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
d.SetId(*read.ID)
log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", loadBalancerName)
stateConf := &resource.StateChangeConf{
Pending: []string{"Accepted", "Updating"},
Target: []string{"Succeeded"},
Refresh: loadbalancerStateRefreshFunc(client, resGroup, loadBalancerName),
Timeout: 10 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", loadBalancerName, err)
}
return resourceArmLoadBalancerProbeRead(d, meta)
}
func resourceArmLoadBalancerProbeRead(d *schema.ResourceData, meta interface{}) error {
loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
configs := *loadBalancer.Properties.Probes
for _, config := range configs {
if *config.Name == d.Get("name").(string) {
d.Set("name", config.Name)
d.Set("protocol", config.Properties.Protocol)
d.Set("interval_in_seconds", config.Properties.IntervalInSeconds)
d.Set("number_of_probes", config.Properties.NumberOfProbes)
d.Set("port", config.Properties.Port)
d.Set("request_path", config.Properties.RequestPath)
break
}
}
return nil
}
func resourceArmLoadBalancerProbeDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
return nil
}
_, index, exists := findLoadBalancerProbeByName(loadBalancer, d.Get("name").(string))
if !exists {
return nil
}
oldProbes := *loadBalancer.Properties.Probes
newProbes := append(oldProbes[:index], oldProbes[index+1:]...)
loadBalancer.Properties.Probes = &newProbes
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
return nil
}
func expandAzureRmLoadBalancerProbe(d *schema.ResourceData, lb *network.LoadBalancer) (*network.Probe, error) {
properties := network.ProbePropertiesFormat{
NumberOfProbes: azure.Int32(int32(d.Get("number_of_probes").(int))),
IntervalInSeconds: azure.Int32(int32(d.Get("interval_in_seconds").(int))),
Port: azure.Int32(int32(d.Get("port").(int))),
}
if v, ok := d.GetOk("protocol"); ok {
properties.Protocol = network.ProbeProtocol(v.(string))
}
if v, ok := d.GetOk("request_path"); ok {
properties.RequestPath = azure.String(v.(string))
}
probe := network.Probe{
Name: azure.String(d.Get("name").(string)),
Properties: &properties,
}
return &probe, nil
}

View File

@ -0,0 +1,144 @@
package azurerm
import (
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAzureRMLoadBalancerProbe_basic(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
probeName := fmt.Sprintf("probe-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerProbe_basic(ri, probeName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerProbeExists(probeName, &lb),
),
},
},
})
}
func TestAccAzureRMLoadBalancerProbe_removal(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
probeName := fmt.Sprintf("probe-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerProbe_basic(ri, probeName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerProbeExists(probeName, &lb),
),
},
{
Config: testAccAzureRMLoadBalancerProbe_removal(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerProbeNotExists(probeName, &lb),
),
},
},
})
}
func testCheckAzureRMLoadBalancerProbeExists(natRuleName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerProbeByName(lb, natRuleName)
if !exists {
return fmt.Errorf("A Probe with name %q cannot be found.", natRuleName)
}
return nil
}
}
func testCheckAzureRMLoadBalancerProbeNotExists(natRuleName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerProbeByName(lb, natRuleName)
if exists {
return fmt.Errorf("A Probe with name %q has been found.", natRuleName)
}
return nil
}
}
func testAccAzureRMLoadBalancerProbe_basic(rInt int, probeName string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_probe" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "%s"
port = 22
}
`, rInt, rInt, rInt, rInt, probeName)
}
func testAccAzureRMLoadBalancerProbe_removal(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
`, rInt, rInt, rInt, rInt)
}

View File

@ -0,0 +1,342 @@
package azurerm
import (
"fmt"
"log"
"regexp"
"time"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/jen20/riviera/azure"
)
func resourceArmLoadBalancerRule() *schema.Resource {
return &schema.Resource{
Create: resourceArmLoadBalancerRuleCreate,
Read: resourceArmLoadBalancerRuleRead,
Update: resourceArmLoadBalancerRuleCreate,
Delete: resourceArmLoadBalancerRuleDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateArmLoadBalancerRuleName,
},
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: azureRMNormalizeLocation,
},
"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"loadbalancer_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"frontend_ip_configuration_name": {
Type: schema.TypeString,
Required: true,
},
"frontend_ip_configuration_id": {
Type: schema.TypeString,
Computed: true,
},
"backend_address_pool_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"protocol": {
Type: schema.TypeString,
Required: true,
},
"frontend_port": {
Type: schema.TypeInt,
Required: true,
},
"backend_port": {
Type: schema.TypeInt,
Required: true,
},
"probe_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"enable_floating_ip": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"idle_timeout_in_minutes": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"load_distribution": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}
func resourceArmLoadBalancerRuleCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
_, _, exists = findLoadBalancerRuleByName(loadBalancer, d.Get("name").(string))
if exists {
return fmt.Errorf("A LoadBalancer Rule with name %q already exists.", d.Get("name").(string))
}
newLbRule, err := expandAzureRmLoadBalancerRule(d, loadBalancer)
if err != nil {
return errwrap.Wrapf("Error Exanding LoadBalancer Rule {{err}}", err)
}
lbRules := append(*loadBalancer.Properties.LoadBalancingRules, *newLbRule)
loadBalancer.Properties.LoadBalancingRules = &lbRules
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
d.SetId(*read.ID)
log.Printf("[DEBUG] Waiting for LoadBalancer (%s) to become available", loadBalancerName)
stateConf := &resource.StateChangeConf{
Pending: []string{"Accepted", "Updating"},
Target: []string{"Succeeded"},
Refresh: loadbalancerStateRefreshFunc(client, resGroup, loadBalancerName),
Timeout: 10 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for LoadBalancer (%s) to become available: %s", loadBalancerName, err)
}
return resourceArmLoadBalancerRuleRead(d, meta)
}
func resourceArmLoadBalancerRuleRead(d *schema.ResourceData, meta interface{}) error {
loadBalancer, exists, err := retrieveLoadBalancerById(d.Id(), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
log.Printf("[INFO] LoadBalancer %q not found. Removing from state", d.Get("name").(string))
return nil
}
configs := *loadBalancer.Properties.LoadBalancingRules
for _, config := range configs {
if *config.Name == d.Get("name").(string) {
d.Set("name", config.Name)
d.Set("protocol", config.Properties.Protocol)
d.Set("frontend_port", config.Properties.FrontendPort)
d.Set("backend_port", config.Properties.BackendPort)
if config.Properties.EnableFloatingIP != nil {
d.Set("enable_floating_ip", config.Properties.EnableFloatingIP)
}
if config.Properties.IdleTimeoutInMinutes != nil {
d.Set("idle_timeout_in_minutes", config.Properties.IdleTimeoutInMinutes)
}
if config.Properties.FrontendIPConfiguration != nil {
d.Set("frontend_ip_configuration_id", config.Properties.FrontendIPConfiguration.ID)
}
if config.Properties.BackendAddressPool != nil {
d.Set("backend_address_pool_id", config.Properties.BackendAddressPool.ID)
}
if config.Properties.Probe != nil {
d.Set("probe_id", config.Properties.Probe.ID)
}
if config.Properties.LoadDistribution != "" {
d.Set("load_distribution", config.Properties.LoadDistribution)
}
}
}
return nil
}
func resourceArmLoadBalancerRuleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
lbClient := client.loadBalancerClient
loadBalancer, exists, err := retrieveLoadBalancerById(d.Get("loadbalancer_id").(string), meta)
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer By ID {{err}}", err)
}
if !exists {
d.SetId("")
return nil
}
_, index, exists := findLoadBalancerRuleByName(loadBalancer, d.Get("name").(string))
if !exists {
return nil
}
oldLbRules := *loadBalancer.Properties.LoadBalancingRules
newLbRules := append(oldLbRules[:index], oldLbRules[index+1:]...)
loadBalancer.Properties.LoadBalancingRules = &newLbRules
resGroup, loadBalancerName, err := resourceGroupAndLBNameFromId(d.Get("loadbalancer_id").(string))
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer Name and Group: {{err}}", err)
}
_, err = lbClient.CreateOrUpdate(resGroup, loadBalancerName, *loadBalancer, make(chan struct{}))
if err != nil {
return errwrap.Wrapf("Error Creating/Updating LoadBalancer {{err}}", err)
}
read, err := lbClient.Get(resGroup, loadBalancerName, "")
if err != nil {
return errwrap.Wrapf("Error Getting LoadBalancer {{err}}", err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read LoadBalancer %s (resource group %s) ID", loadBalancerName, resGroup)
}
return nil
}
func expandAzureRmLoadBalancerRule(d *schema.ResourceData, lb *network.LoadBalancer) (*network.LoadBalancingRule, error) {
properties := network.LoadBalancingRulePropertiesFormat{
Protocol: network.TransportProtocol(d.Get("protocol").(string)),
FrontendPort: azure.Int32(int32(d.Get("frontend_port").(int))),
BackendPort: azure.Int32(int32(d.Get("backend_port").(int))),
EnableFloatingIP: azure.Bool(d.Get("enable_floating_ip").(bool)),
}
if v, ok := d.GetOk("idle_timeout_in_minutes"); ok {
properties.IdleTimeoutInMinutes = azure.Int32(int32(v.(int)))
}
if v := d.Get("load_distribution").(string); v != "" {
properties.LoadDistribution = network.LoadDistribution(v)
}
if v := d.Get("frontend_ip_configuration_name").(string); v != "" {
rule, _, exists := findLoadBalancerFrontEndIpConfigurationByName(lb, v)
if !exists {
return nil, fmt.Errorf("[ERROR] Cannot find FrontEnd IP Configuration with the name %s", v)
}
feip := network.SubResource{
ID: rule.ID,
}
properties.FrontendIPConfiguration = &feip
}
if v := d.Get("backend_address_pool_id").(string); v != "" {
beAP := network.SubResource{
ID: &v,
}
properties.BackendAddressPool = &beAP
}
if v := d.Get("probe_id").(string); v != "" {
pid := network.SubResource{
ID: &v,
}
properties.Probe = &pid
}
lbRule := network.LoadBalancingRule{
Name: azure.String(d.Get("name").(string)),
Properties: &properties,
}
return &lbRule, nil
}
func validateArmLoadBalancerRuleName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[a-zA-Z._-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only word characters and hyphens allowed in %q: %q",
k, value))
}
if len(value) > 80 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 80 characters: %q", k, value))
}
if len(value) == 0 {
errors = append(errors, fmt.Errorf(
"%q cannot be an empty string: %q", k, value))
}
if !regexp.MustCompile(`[a-zA-Z]$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q must end with a word character: %q", k, value))
}
if !regexp.MustCompile(`^[a-zA-Z]`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q must start with a word character: %q", k, value))
}
return
}

View File

@ -0,0 +1,196 @@
package azurerm
import (
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestResourceAzureRMLoadBalancerRuleNameLabel_validation(t *testing.T) {
cases := []struct {
Value string
ErrCount int
}{
{
Value: "-word",
ErrCount: 1,
},
{
Value: "testing-",
ErrCount: 1,
},
{
Value: "test123test",
ErrCount: 1,
},
{
Value: acctest.RandStringFromCharSet(81, "abcdedfed"),
ErrCount: 1,
},
{
Value: "test.rule",
ErrCount: 0,
},
{
Value: "test_rule",
ErrCount: 0,
},
{
Value: "test-rule",
ErrCount: 0,
},
{
Value: "TestRule",
ErrCount: 0,
},
}
for _, tc := range cases {
_, errors := validateArmLoadBalancerRuleName(tc.Value, "azurerm_lb_rule")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected the Azure RM LoadBalancer Rule Name Label to trigger a validation error")
}
}
}
func TestAccAzureRMLoadBalancerRule_basic(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
lbRuleName := fmt.Sprintf("LbRule-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerRule_basic(ri, lbRuleName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerRuleExists(lbRuleName, &lb),
),
},
},
})
}
func TestAccAzureRMLoadBalancerRule_removal(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
lbRuleName := fmt.Sprintf("LbRule-%d", ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancerRule_basic(ri, lbRuleName),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerRuleExists(lbRuleName, &lb),
),
},
{
Config: testAccAzureRMLoadBalancerRule_removal(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
testCheckAzureRMLoadBalancerRuleNotExists(lbRuleName, &lb),
),
},
},
})
}
func testCheckAzureRMLoadBalancerRuleExists(lbRuleName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerRuleByName(lb, lbRuleName)
if !exists {
return fmt.Errorf("A LoadBalancer Rule with name %q cannot be found.", lbRuleName)
}
return nil
}
}
func testCheckAzureRMLoadBalancerRuleNotExists(lbRuleName string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, _, exists := findLoadBalancerRuleByName(lb, lbRuleName)
if exists {
return fmt.Errorf("A LoadBalancer Rule with name %q has been found.", lbRuleName)
}
return nil
}
}
func testAccAzureRMLoadBalancerRule_basic(rInt int, lbRuleName string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_rule" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "%s"
protocol = "Tcp"
frontend_port = 3389
backend_port = 3389
frontend_ip_configuration_name = "one-%d"
}
`, rInt, rInt, rInt, rInt, lbRuleName, rInt)
}
func testAccAzureRMLoadBalancerRule_removal(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
`, rInt, rInt, rInt, rInt)
}

View File

@ -0,0 +1,293 @@
package azurerm
import (
"fmt"
"net/http"
"testing"
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestResourceAzureRMLoadBalancerPrivateIpAddressAllocation_validation(t *testing.T) {
cases := []struct {
Value string
ErrCount int
}{
{
Value: "Random",
ErrCount: 1,
},
{
Value: "Static",
ErrCount: 0,
},
{
Value: "Dynamic",
ErrCount: 0,
},
{
Value: "STATIC",
ErrCount: 0,
},
{
Value: "static",
ErrCount: 0,
},
}
for _, tc := range cases {
_, errors := validateLoadBalancerPrivateIpAddressAllocation(tc.Value, "azurerm_lb")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected the Azure RM LoadBalancer private_ip_address_allocation to trigger a validation error")
}
}
}
func TestAccAzureRMLoadBalancer_basic(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancer_basic(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
),
},
},
})
}
func TestAccAzureRMLoadBalancer_frontEndConfig(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancer_frontEndConfig(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
resource.TestCheckResourceAttr(
"azurerm_lb.test", "frontend_ip_configuration.#", "2"),
),
},
{
Config: testAccAzureRMLoadBalancer_frontEndConfigRemoval(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
resource.TestCheckResourceAttr(
"azurerm_lb.test", "frontend_ip_configuration.#", "1"),
),
},
},
})
}
func TestAccAzureRMLoadBalancer_tags(t *testing.T) {
var lb network.LoadBalancer
ri := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMLoadBalancer_basic(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
resource.TestCheckResourceAttr(
"azurerm_lb.test", "tags.%", "2"),
resource.TestCheckResourceAttr(
"azurerm_lb.test", "tags.Environment", "production"),
resource.TestCheckResourceAttr(
"azurerm_lb.test", "tags.Purpose", "AcceptanceTests"),
),
},
{
Config: testAccAzureRMLoadBalancer_updatedTags(ri),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
resource.TestCheckResourceAttr(
"azurerm_lb.test", "tags.%", "1"),
resource.TestCheckResourceAttr(
"azurerm_lb.test", "tags.Purpose", "AcceptanceTests"),
),
},
},
})
}
func testCheckAzureRMLoadBalancerExists(name string, lb *network.LoadBalancer) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
loadbalancerName := 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 loadbalancer: %s", loadbalancerName)
}
conn := testAccProvider.Meta().(*ArmClient).loadBalancerClient
resp, err := conn.Get(resourceGroup, loadbalancerName, "")
if err != nil {
if resp.StatusCode == http.StatusNotFound {
return fmt.Errorf("Bad: LoadBalancer %q (resource group: %q) does not exist", loadbalancerName, resourceGroup)
}
return fmt.Errorf("Bad: Get on loadBalancerClient: %s", err)
}
*lb = resp
return nil
}
}
func testCheckAzureRMLoadBalancerDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*ArmClient).loadBalancerClient
for _, rs := range s.RootModule().Resources {
if rs.Type != "azurerm_lb" {
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("LoadBalancer still exists:\n%#v", resp.Properties)
}
}
return nil
}
func testAccAzureRMLoadBalancer_basic(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
tags {
Environment = "production"
Purpose = "AcceptanceTests"
}
}`, rInt, rInt)
}
func testAccAzureRMLoadBalancer_updatedTags(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
tags {
Purpose = "AcceptanceTests"
}
}`, rInt, rInt)
}
func testAccAzureRMLoadBalancer_frontEndConfig(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_public_ip" "test1" {
name = "another-test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
frontend_ip_configuration {
name = "two-%d"
public_ip_address_id = "${azurerm_public_ip.test1.id}"
}
}`, rInt, rInt, rInt, rInt, rInt, rInt)
}
func testAccAzureRMLoadBalancer_frontEndConfigRemoval(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "test-ip-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "arm-test-loadbalancer-%d"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "one-%d"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}`, rInt, rInt, rInt, rInt)
}

View File

@ -11,6 +11,7 @@ func tagsSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeMap,
Optional: true,
Computed: true,
ValidateFunc: validateAzureRMTags,
}
}

View File

@ -0,0 +1,62 @@
---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_lb"
sidebar_current: "docs-azurerm-resource-loadbalancer"
description: |-
Create a LoadBalancer Resource.
---
# azurerm\_lb
Create a LoadBalancer Resource.
## Example Usage
```
resource "azurerm_resource_group" "test" {
name = "LoadBalancerRG"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "PublicIPForLB"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "TestLoadBalancer"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) Specifies the name of the LoadBalancer.
* `resource_group_name` - (Required) The name of the resource group in which to create the LoadBalancer.
* `location` - (Required) Specifies the supported Azure location where the resource exists.
* `frontend_ip_configuration` - (Optional) A frontend ip configuration block as documented below.
* `tags` - (Optional) A mapping of tags to assign to the resource.
`frontend_ip_configuration` supports the following:
* `name` - (Required) Specifies the name of the frontend ip configuration.
* `subnet_id` - (Optional) Reference to subnet associated with the IP Configuration.
* `private_ip_address` - (Optional) Private IP Address to assign to the Load Balancer. The last one and first four IPs in any range are reserved and cannot be manually assigned.
* `public_ip_address_id` - (Optional) Reference to Public IP address to be associated with the Load Balancer.
## Attributes Reference
The following attributes are exported:
* `id` - The LoadBalancer ID.

View File

@ -0,0 +1,62 @@
---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_lb_backend_address_pool"
sidebar_current: "docs-azurerm-resource-loadbalancer-backend-address-pool"
description: |-
Create a LoadBalancer Backend Address Pool.
---
# azurerm\_lb\_backend\_address\_pool
Create a LoadBalancer Backend Address Pool.
~> **NOTE When using this resource, the LoadBalancer needs to have a FrontEnd IP Configuration Attached
## Example Usage
```
resource "azurerm_resource_group" "test" {
name = "LoadBalancerRG"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "PublicIPForLB"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "TestLoadBalancer"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_backend_address_pool" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "BackEndAddressPool"
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) Specifies the name of the Backend Address Pool.
* `resource_group_name` - (Required) The name of the resource group in which to create the resource.
* `location` - (Required) Specifies the supported Azure location where the resource exists.
* `loadbalancer_id` - (Required) The ID of the LoadBalancer in which to create the Backend Address Pool.
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the LoadBalancer to which the resource is attached.

View File

@ -0,0 +1,72 @@
---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_lb_nat_pool"
sidebar_current: "docs-azurerm-resource-loadbalancer-nat-pool"
description: |-
Create a LoadBalancer NAT Pool.
---
# azurerm\_lb\_nat\_pool
Create a LoadBalancer NAT pool.
~> **NOTE When using this resource, the LoadBalancer needs to have a FrontEnd IP Configuration Attached
## Example Usage
```
resource "azurerm_resource_group" "test" {
name = "LoadBalancerRG"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "PublicIPForLB"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "TestLoadBalancer"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_nat_pool" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "SampleApplication Pool"
protocol = "Tcp"
frontend_port_start = 80
frontend_port_end = 81
backend_port = 8080
frontend_ip_configuration_name = "PublicIPAddress"
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) Specifies the name of the NAT pool.
* `resource_group_name` - (Required) The name of the resource group in which to create the resource.
* `location` - (Required) Specifies the supported Azure location where the resource exists.
* `loadbalancer_id` - (Required) The ID of the LoadBalancer in which to create the NAT pool.
* `frontend_ip_configuration_name` - (Required) The name of the frontend IP configuration exposing this rule.
* `protocol` - (Required) The transport protocol for the external endpoint. Possible values are `Udp` or `Tcp`.
* `frontend_port_start` - (Required) The first port number in the range of external ports that will be used to provide Inbound Nat to NICs associated with this Load Balancer. Possible values range between 1 and 65534, inclusive.
* `frontend_port_end` - (Required) The last port number in the range of external ports that will be used to provide Inbound Nat to NICs associated with this Load Balancer. Possible values range between 1 and 65534, inclusive.
* `backend_port` - (Required) The port used for the internal endpoint. Possible values range between 1 and 65535, inclusive.
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the LoadBalancer to which the resource is attached.

View File

@ -0,0 +1,70 @@
---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_lb_nat_rule"
sidebar_current: "docs-azurerm-resource-loadbalancer-nat-rule"
description: |-
Create a LoadBalancer NAT Rule.
---
# azurerm\_lb\_nat\_rule
Create a LoadBalancer NAT Rule.
~> **NOTE When using this resource, the LoadBalancer needs to have a FrontEnd IP Configuration Attached
## Example Usage
```
resource "azurerm_resource_group" "test" {
name = "LoadBalancerRG"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "PublicIPForLB"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "TestLoadBalancer"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_nat_rule" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "RDP Access"
protocol = "Tcp"
frontend_port = 3389
backend_port = 3389
frontend_ip_configuration_name = "PublicIPAddress"
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) Specifies the name of the NAT Rule.
* `resource_group_name` - (Required) The name of the resource group in which to create the resource.
* `location` - (Required) Specifies the supported Azure location where the resource exists.
* `loadbalancer_id` - (Required) The ID of the LoadBalancer in which to create the NAT Rule.
* `frontend_ip_configuration_name` - (Required) The name of the frontend IP configuration exposing this rule.
* `protocol` - (Required) The transport protocol for the external endpoint. Possible values are `Udp` or `Tcp`.
* `frontend_port` - (Required) The port for the external endpoint. Port numbers for each Rule must be unique within the Load Balancer. Possible values range between 1 and 65534, inclusive.
* `backend_port` - (Required) The port used for internal connections on the endpoint. Possible values range between 1 and 65535, inclusive.
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the LoadBalancer to which the resource is attached.

View File

@ -0,0 +1,70 @@
---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_lb_probe"
sidebar_current: "docs-azurerm-resource-loadbalancer-probe"
description: |-
Create a LoadBalancer Probe Resource.
---
# azurerm\_lb\_probe
Create a LoadBalancer Probe Resource.
~> **NOTE When using this resource, the LoadBalancer needs to have a FrontEnd IP Configuration Attached
## Example Usage
```
resource "azurerm_resource_group" "test" {
name = "LoadBalancerRG"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "PublicIPForLB"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "TestLoadBalancer"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_probe" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "SSH Running Probe"
port = 22
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) Specifies the name of the Probe.
* `resource_group_name` - (Required) The name of the resource group in which to create the resource.
* `location` - (Required) Specifies the supported Azure location where the resource exists.
* `loadbalancer_id` - (Required) The ID of the LoadBalancer in which to create the NAT Rule.
* `protocol` - (Optional) Specifies the protocol of the end point. Possible values are `Http` or `Tcp`. If Tcp is specified, a received ACK is required for the probe to be successful. If Http is specified, a 200 OK response from the specified URI is required for the probe to be successful.
* `port` - (Required) Port on which the Probe queries the backend endpoint. Possible values range from 1 to 65535, inclusive.
* `request_path` - (Optional) The URI used for requesting health status from the backend endpoint. Required if protocol is set to Http. Otherwise, it is not allowed.
* `interval_in_seconds` - (Optional) The interval, in seconds between probes to the backend endpoint for health status. The default value is 15, the minimum value is 5.
* `number_of_probes` - (Optional) The number of failed probe attempts after which the backend endpoint is removed from rotation. The default value is 2. NumberOfProbes multiplied by intervalInSeconds value must be greater or equal to 10.Endpoints are returned to rotation when at least one probe is successful.
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the LoadBalancer to which the resource is attached.

View File

@ -0,0 +1,75 @@
---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_lb_rule"
sidebar_current: "docs-azurerm-resource-loadbalancer-rule"
description: |-
Create a LoadBalancer Rule.
---
# azurerm\_lb\_rule
Create a LoadBalancer Rule.
~> **NOTE When using this resource, the LoadBalancer needs to have a FrontEnd IP Configuration Attached
## Example Usage
```
resource "azurerm_resource_group" "test" {
name = "LoadBalancerRG"
location = "West US"
}
resource "azurerm_public_ip" "test" {
name = "PublicIPForLB"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "TestLoadBalancer"
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_rule" "test" {
location = "West US"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
name = "LBRule"
protocol = "Tcp"
frontend_port = 3389
backend_port = 3389
frontend_ip_configuration_name = "PublicIPAddress"
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) Specifies the name of the LB Rule.
* `resource_group_name` - (Required) The name of the resource group in which to create the resource.
* `location` - (Required) Specifies the supported Azure location where the resource exists.
* `loadbalancer_id` - (Required) The ID of the LoadBalancer in which to create the Rule.
* `frontend_ip_configuration_name` - (Required) The name of the frontend IP configuration to which the rule is associated.
* `protocol` - (Required) The transport protocol for the external endpoint. Possible values are `Udp` or `Tcp`.
* `frontend_port` - (Required) The port for the external endpoint. Port numbers for each Rule must be unique within the Load Balancer. Possible values range between 1 and 65534, inclusive.
* `backend_port` - (Required) The port used for internal connections on the endpoint. Possible values range between 1 and 65535, inclusive.
* `backend_address_pool_id` - (Optional) A reference to a Backend Address Pool over which this Load Balancing Rule operates.
* `probe_id` - (Optional) A reference to a Probe used by this Load Balancing Rule.
* `enable_floating_ip` - (Optional) Floating IP is pertinent to failover scenarios: a “floating” IP is reassigned to a secondary server in case the primary server fails. Floating IP is required for SQL AlwaysOn.
* `idle_timeout_in_minutes` - (Optional) Specifies the timeout for the Tcp idle connection. The value can be set between 4 and 30 minutes. The default value is 4 minutes. This element is only used when the protocol is set to Tcp.
* `load_distribution` - (Optional) Specifies the load balancing distribution type to be used by the Load Balancer. Possible values are: Default The load balancer is configured to use a 5 tuple hash to map traffic to available servers. SourceIP The load balancer is configured to use a 2 tuple hash to map traffic to available servers. SourceIPProtocol The load balancer is configured to use a 3 tuple hash to map traffic to available servers.
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the LoadBalancer to which the resource is attached.

View File

@ -74,6 +74,37 @@
</ul>
</li>
<li<%= sidebar_current(/^docs-azurerm-resource-loadbalancer/) %>>
<a href="#">Load Balancer Resources</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-azurerm-resource-loadbalancer") %>>
<a href="/docs/providers/azurerm/r/loadbalancer.html">azurerm_lb</a>
</li>
<li<%= sidebar_current("docs-azurerm-resource-loadbalancer-backend-address-pool") %>>
<a href="/docs/providers/azurerm/r/loadbalancer_backend_address_pool.html">azurerm_lb_backend_address_pool</a>
</li>
<li<%= sidebar_current("docs-azurerm-resource-loadbalancer-rule") %>>
<a href="/docs/providers/azurerm/r/loadbalancer_rule.html">azurerm_lb_rule</a>
</li>
<li<%= sidebar_current("docs-azurerm-resource-loadbalancer-nat-rule") %>>
<a href="/docs/providers/azurerm/r/loadbalancer_nat_rule.html">azurerm_lb_nat_rule</a>
</li>
<li<%= sidebar_current("docs-azurerm-resource-loadbalancer-nat-pool") %>>
<a href="/docs/providers/azurerm/r/loadbalancer_nat_pool.html">azurerm_lb_nat_pool</a>
</li>
<li<%= sidebar_current("docs-azurerm-resource-loadbalancer-probe") %>>
<a href="/docs/providers/azurerm/r/loadbalancer_probe.html">azurerm_lb_probe</a>
</li>
</ul>
</li>
<li<%= sidebar_current(/^docs-azurerm-resource-network/) %>>
<a href="#">Network Resources</a>
<ul class="nav nav-visible">