diff --git a/azurerm/resource_arm_traffic_manager_profile.go b/azurerm/resource_arm_traffic_manager_profile.go index 84bbb7552781..d7c14bf18c39 100644 --- a/azurerm/resource_arm_traffic_manager_profile.go +++ b/azurerm/resource_arm_traffic_manager_profile.go @@ -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, @@ -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 @@ -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), } @@ -230,12 +254,17 @@ 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 { @@ -243,22 +272,32 @@ func getArmTrafficManagerProfileProperties(d *schema.ResourceData) *trafficmanag 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 { @@ -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} } @@ -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 != "" { + 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()) diff --git a/azurerm/resource_arm_traffic_manager_profile_test.go b/azurerm/resource_arm_traffic_manager_profile_test.go index fc26ae80e9a0..02438c66a354 100644 --- a/azurerm/resource_arm_traffic_manager_profile_test.go +++ b/azurerm/resource_arm_traffic_manager_profile_test.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "net/http" + "regexp" "testing" "github.com/hashicorp/terraform/helper/resource" @@ -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 @@ -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) +} diff --git a/examples/traffic-manager/basic/main.tf b/examples/traffic-manager/basic/main.tf index 7c31dc423a8f..1157f126b669 100644 --- a/examples/traffic-manager/basic/main.tf +++ b/examples/traffic-manager/basic/main.tf @@ -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 } } diff --git a/website/docs/r/traffic_manager_endpoint.html.markdown b/website/docs/r/traffic_manager_endpoint.html.markdown index e8c0f2810aaa..b6b237b255ae 100644 --- a/website/docs/r/traffic_manager_endpoint.html.markdown +++ b/website/docs/r/traffic_manager_endpoint.html.markdown @@ -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 = { diff --git a/website/docs/r/traffic_manager_profile.html.markdown b/website/docs/r/traffic_manager_profile.html.markdown index 787180aaebb8..4b1f03553c14 100644 --- a/website/docs/r/traffic_manager_profile.html.markdown +++ b/website/docs/r/traffic_manager_profile.html.markdown @@ -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 = { @@ -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: