Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_traffic_manager_profile - support for the interval_in_seconds, timeout_in_seconds, and tolerated_number_of_failures properties #3473

Merged
merged 5 commits into from
Aug 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 65 additions & 10 deletions azurerm/resource_arm_traffic_manager_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ func resourceArmTrafficManagerProfile() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"interval_in_seconds": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntInSlice([]int{10, 30}),
Default: 30,
},
"timeout_in_seconds": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(5, 10),
Default: 10,
},
"tolerated_number_of_failures": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(0, 9),
Default: 3,
},
},
},
Set: resourceAzureRMTrafficManagerMonitorConfigHash,
Expand All @@ -122,7 +140,7 @@ func resourceArmTrafficManagerProfileCreateUpdate(d *schema.ResourceData, meta i
client := meta.(*ArmClient).trafficManager.ProfilesClient
ctx := meta.(*ArmClient).StopContext

log.Printf("[INFO] preparing arguments for Azure ARM virtual network creation.")
log.Printf("[INFO] preparing arguments for TrafficManager Profile creation.")

name := d.Get("name").(string)
// must be provided in request
Expand All @@ -143,10 +161,16 @@ func resourceArmTrafficManagerProfileCreateUpdate(d *schema.ResourceData, meta i
}
}

props, err := getArmTrafficManagerProfileProperties(d)
if err != nil {
// There isn't any additional messaging needed for this error
return err
}

profile := trafficmanager.Profile{
Name: &name,
Location: &location,
ProfileProperties: getArmTrafficManagerProfileProperties(d),
ProfileProperties: props,
Tags: expandTags(tags),
}

Expand Down Expand Up @@ -230,35 +254,50 @@ func resourceArmTrafficManagerProfileDelete(d *schema.ResourceData, meta interfa
return nil
}

func getArmTrafficManagerProfileProperties(d *schema.ResourceData) *trafficmanager.ProfileProperties {
func getArmTrafficManagerProfileProperties(d *schema.ResourceData) (*trafficmanager.ProfileProperties, error) {
routingMethod := d.Get("traffic_routing_method").(string)

montiorConfig, err := expandArmTrafficManagerMonitorConfig(d)
if err != nil {
return nil, fmt.Errorf("Error expanding `montior_config`: %+v", err)
}
props := &trafficmanager.ProfileProperties{
TrafficRoutingMethod: trafficmanager.TrafficRoutingMethod(routingMethod),
DNSConfig: expandArmTrafficManagerDNSConfig(d),
MonitorConfig: expandArmTrafficManagerMonitorConfig(d),
MonitorConfig: montiorConfig,
}

if status, ok := d.GetOk("profile_status"); ok {
s := status.(string)
props.ProfileStatus = trafficmanager.ProfileStatus(s)
}

return props
return props, nil
}

func expandArmTrafficManagerMonitorConfig(d *schema.ResourceData) *trafficmanager.MonitorConfig {
func expandArmTrafficManagerMonitorConfig(d *schema.ResourceData) (*trafficmanager.MonitorConfig, error) {
monitorSets := d.Get("monitor_config").(*schema.Set).List()
monitor := monitorSets[0].(map[string]interface{})

proto := monitor["protocol"].(string)
port := int64(monitor["port"].(int))
path := monitor["path"].(string)
interval := int64(monitor["interval_in_seconds"].(int))
timeout := int64(monitor["timeout_in_seconds"].(int))
tolerated := int64(monitor["tolerated_number_of_failures"].(int))

return &trafficmanager.MonitorConfig{
Protocol: trafficmanager.MonitorProtocol(proto),
Port: &port,
Path: &path,
if interval == int64(10) && timeout == int64(10) {
return nil, fmt.Errorf("`timeout_in_seconds` must be between `5` and `9` when `interval_in_seconds` is set to `10`")
}

return &trafficmanager.MonitorConfig{
Protocol: trafficmanager.MonitorProtocol(proto),
Port: &port,
Path: &path,
IntervalInSeconds: &interval,
TimeoutInSeconds: &timeout,
ToleratedNumberOfFailures: &tolerated,
}, nil
}

func expandArmTrafficManagerDNSConfig(d *schema.ResourceData) *trafficmanager.DNSConfig {
Expand Down Expand Up @@ -293,6 +332,10 @@ func flattenAzureRMTrafficManagerProfileMonitorConfig(cfg *trafficmanager.Monito
result["path"] = *cfg.Path
}

result["interval_in_seconds"] = int(*cfg.IntervalInSeconds)
result["timeout_in_seconds"] = int(*cfg.TimeoutInSeconds)
result["tolerated_number_of_failures"] = int(*cfg.ToleratedNumberOfFailures)

return []interface{}{result}
}

Expand All @@ -317,6 +360,18 @@ func resourceAzureRMTrafficManagerMonitorConfigHash(v interface{}) int {
if v, ok := m["path"]; ok && v != "" {
buf.WriteString(fmt.Sprintf("%s-", m["path"].(string)))
}

if v, ok := m["interval_in_seconds"]; ok && v != "" {
katbyte marked this conversation as resolved.
Show resolved Hide resolved
buf.WriteString(fmt.Sprintf("%d-", m["interval_in_seconds"].(int)))
}

if v, ok := m["timeout_in_seconds"]; ok && v != "" {
buf.WriteString(fmt.Sprintf("%d-", m["timeout_in_seconds"].(int)))
}

if v, ok := m["tolerated_number_of_failures"]; ok && v != "" {
buf.WriteString(fmt.Sprintf("%d-", m["tolerated_number_of_failures"].(int)))
}
}

return hashcode.String(buf.String())
Expand Down
141 changes: 141 additions & 0 deletions azurerm/resource_arm_traffic_manager_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"log"
"net/http"
"regexp"
"testing"

"github.com/hashicorp/terraform/helper/resource"
Expand Down Expand Up @@ -310,6 +311,59 @@ func TestAccAzureRMTrafficManagerProfile_priorityToWeighted(t *testing.T) {
})
}

func TestAccAzureRMTrafficManagerProfile_fastEndpointFailoverSettings(t *testing.T) {
resourceName := "azurerm_traffic_manager_profile.test"
rInt := tf.AccRandTimeInt()
location := testLocation()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMTrafficManagerProfileDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMTrafficManagerProfile_failover(rInt, location),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMTrafficManagerProfileExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAzureRMTrafficManagerProfile_failoverUpdate(rInt, location),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMTrafficManagerProfileExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMTrafficManagerProfile_fastEndpointFailoverSettingsError(t *testing.T) {
rInt := tf.AccRandTimeInt()
location := testLocation()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMTrafficManagerProfileDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMTrafficManagerProfile_failoverError(rInt, location),
ExpectError: regexp.MustCompile("`timeout_in_seconds` must be between `5` and `9` when `interval_in_seconds` is set to `10`"),
},
},
})
}

func testCheckAzureRMTrafficManagerProfileExists(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
// Ensure we have enough information in state to look up in API
Expand Down Expand Up @@ -577,3 +631,90 @@ resource "azurerm_traffic_manager_profile" "test" {
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMTrafficManagerProfile_failover(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_traffic_manager_profile" "test" {
name = "acctesttmp%d"
resource_group_name = "${azurerm_resource_group.test.name}"
traffic_routing_method = "Performance"

dns_config {
relative_name = "acctesttmp%d"
ttl = 30
}

monitor_config {
protocol = "https"
port = 443
path = "/"
interval_in_seconds = 30
timeout_in_seconds = 6
tolerated_number_of_failures = 3
}
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMTrafficManagerProfile_failoverUpdate(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_traffic_manager_profile" "test" {
name = "acctesttmp%d"
resource_group_name = "${azurerm_resource_group.test.name}"
traffic_routing_method = "Performance"

dns_config {
relative_name = "acctesttmp%d"
ttl = 30
}

monitor_config {
protocol = "https"
port = 443
path = "/"
interval_in_seconds = 30
timeout_in_seconds = 9
tolerated_number_of_failures = 6
}
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMTrafficManagerProfile_failoverError(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_traffic_manager_profile" "test" {
name = "acctesttmp%d"
resource_group_name = "${azurerm_resource_group.test.name}"
traffic_routing_method = "Performance"

dns_config {
relative_name = "acctesttmp%d"
ttl = 30
}

monitor_config {
protocol = "https"
port = 443
path = "/"
interval_in_seconds = 10
timeout_in_seconds = 10
tolerated_number_of_failures = 3
}
}
`, rInt, location, rInt, rInt)
}
9 changes: 6 additions & 3 deletions examples/traffic-manager/basic/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ resource "azurerm_traffic_manager_profile" "example" {
}

monitor_config {
protocol = "http"
port = 80
path = "/"
protocol = "http"
port = 80
path = "/"
interval_in_seconds = 30
timeout_in_seconds = 9
tolerated_number_of_failures = 3
}
}
9 changes: 6 additions & 3 deletions website/docs/r/traffic_manager_endpoint.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ resource "azurerm_traffic_manager_profile" "test" {
}

monitor_config {
protocol = "http"
port = 80
path = "/"
protocol = "http"
port = 80
path = "/"
interval_in_seconds = 30
timeout_in_seconds = 9
tolerated_number_of_failures = 3
}

tags = {
Expand Down
15 changes: 12 additions & 3 deletions website/docs/r/traffic_manager_profile.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ resource "azurerm_traffic_manager_profile" "test" {
}

monitor_config {
protocol = "http"
port = 80
path = "/"
protocol = "http"
port = 80
path = "/"
interval_in_seconds = 30
timeout_in_seconds = 9
tolerated_number_of_failures = 3
}

tags = {
Expand Down Expand Up @@ -97,6 +100,12 @@ The `monitor_config` block supports:

* `path` - (Optional) The path used by the monitoring checks. Required when `protocol` is set to `HTTP` or `HTTPS` - cannot be set when `protocol` is set to `TCP`.

* `interval_in_seconds` - (Optional) The interval used to check the endpoint health from a Traffic Manager probing agent. You can specify two values here: `30` (normal probing) and `10` (fast probing). The default value is `30`.

* `timeout_in_seconds` - (Optional) The amount of time the Traffic Manager probing agent should wait before considering that check a failure when a health check probe is sent to the endpoint. If `interval_in_seconds` is set to `30`, then `timeout_in_seconds` can be between `5` and `10`. The default value is `10`. If `interval_in_seconds` is set to `10`, then valid values are between `5` and `9` and `timeout_in_seconds` is required.

* `tolerated_number_of_failures` - (Optional) The number of failures a Traffic Manager probing agent tolerates before marking that endpoint as unhealthy. Valid values are between `0` and `9`. The default value is `3`

## Attributes Reference

The following attributes are exported:
Expand Down