From 67d4a881923454f31a381122cb5471061dc904df Mon Sep 17 00:00:00 2001 From: Maikel van den Hurk Date: Mon, 20 May 2019 08:34:35 +0200 Subject: [PATCH 1/3] Add missing monitor config features to Traffic Manager --- .../resource_arm_traffic_manager_profile.go | 45 ++++++++++++-- ...source_arm_traffic_manager_profile_test.go | 58 +++++++++++++++++++ examples/traffic-manager/basic/main.tf | 9 ++- .../r/traffic_manager_endpoint.html.markdown | 9 ++- .../r/traffic_manager_profile.html.markdown | 15 ++++- 5 files changed, 123 insertions(+), 13 deletions(-) diff --git a/azurerm/resource_arm_traffic_manager_profile.go b/azurerm/resource_arm_traffic_manager_profile.go index c7b56707e47c..734646caf5f3 100644 --- a/azurerm/resource_arm_traffic_manager_profile.go +++ b/azurerm/resource_arm_traffic_manager_profile.go @@ -107,6 +107,21 @@ func resourceArmTrafficManagerProfile() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "interval_in_seconds": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntInSlice([]int{10, 30}), + }, + "timeout_in_seconds": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(5, 10), + }, + "tolerated_number_of_failures": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 9), + }, }, }, Set: resourceAzureRMTrafficManagerMonitorConfigHash, @@ -121,7 +136,7 @@ func resourceArmTrafficManagerProfileCreateUpdate(d *schema.ResourceData, meta i client := meta.(*ArmClient).trafficManagerProfilesClient 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 @@ -252,11 +267,17 @@ func expandArmTrafficManagerMonitorConfig(d *schema.ResourceData) *trafficmanage 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, + Protocol: trafficmanager.MonitorProtocol(proto), + Port: &port, + Path: &path, + IntervalInSeconds: &interval, + TimeoutInSeconds: &timeout, + ToleratedNumberOfFailures: &tolerated, } } @@ -292,6 +313,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} } @@ -316,6 +341,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 aad2fd0bc4b5..4da504c346d2 100644 --- a/azurerm/resource_arm_traffic_manager_profile_test.go +++ b/azurerm/resource_arm_traffic_manager_profile_test.go @@ -310,6 +310,35 @@ 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), + resource.TestCheckResourceAttr(resourceName, "monitor_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "monitor_config.3418284669.interval_in_seconds", "30"), + resource.TestCheckResourceAttr(resourceName, "monitor_config.3418284669.timeout_in_seconds", "6"), + resource.TestCheckResourceAttr(resourceName, "monitor_config.3418284669.tolerated_number_of_failures", "3"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + 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 +606,32 @@ 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) +} 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 131744b775d0..08e07d3373fa 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..13105570e801 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 seconds (normal probing) and 10 seconds (fast probing). If no values are provided, the profile sets to a default value of 30 seconds. + +* `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 the Probing Interval is set to 30 seconds, then you can set the Timeout value between 5 and 10 seconds. If no value is specified, it uses a default value of 10 seconds. If the Probing Interval is set to 10 seconds, then you can set the Timeout value between 5 and 9 seconds. If no Timeout value is specified, it uses a default value of 9 seconds. + +* `tolerated_number_of_failures` - (Optional) The number of failures a Traffic Manager probing agent tolerates before marking that endpoint as unhealthy. Its value can range between 0 and 9. A value of 0 means a single monitoring failure can cause that endpoint to be marked as unhealthy. If no value is specified, it uses the default value of 3. + ## Attributes Reference The following attributes are exported: From 128430ddc808a50b6dec9677ba5957c350517b42 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Fri, 2 Aug 2019 14:57:36 -0700 Subject: [PATCH 2/3] start of review fixes --- azurerm/resource_arm_traffic_manager_profile.go | 3 +++ website/docs/r/traffic_manager_profile.html.markdown | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_traffic_manager_profile.go b/azurerm/resource_arm_traffic_manager_profile.go index b11731823142..e3c1c4a4fe39 100644 --- a/azurerm/resource_arm_traffic_manager_profile.go +++ b/azurerm/resource_arm_traffic_manager_profile.go @@ -112,16 +112,19 @@ func resourceArmTrafficManagerProfile() *schema.Resource { 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, }, }, }, diff --git a/website/docs/r/traffic_manager_profile.html.markdown b/website/docs/r/traffic_manager_profile.html.markdown index 13105570e801..e94a9a9bb9ac 100644 --- a/website/docs/r/traffic_manager_profile.html.markdown +++ b/website/docs/r/traffic_manager_profile.html.markdown @@ -100,9 +100,9 @@ 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 seconds (normal probing) and 10 seconds (fast probing). If no values are provided, the profile sets to a default value of 30 seconds. +* `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` seconds (normal probing) and `10` seconds (fast probing). If no values are provided, the profile sets to a default value of `30` seconds. -* `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 the Probing Interval is set to 30 seconds, then you can set the Timeout value between 5 and 10 seconds. If no value is specified, it uses a default value of 10 seconds. If the Probing Interval is set to 10 seconds, then you can set the Timeout value between 5 and 9 seconds. If no Timeout value is specified, it uses a default value of 9 seconds. +* `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 the Probing Interval is set to `30` seconds, then you can set the Timeout value between `5` and `10` seconds. If no value is specified, it uses a default value of `10` seconds. If the Probing Interval is set to `10` seconds, then you can set the Timeout value between `5` and `9` seconds. If no Timeout value is specified, it uses a default value of `9` seconds. * `tolerated_number_of_failures` - (Optional) The number of failures a Traffic Manager probing agent tolerates before marking that endpoint as unhealthy. Its value can range between 0 and 9. A value of 0 means a single monitoring failure can cause that endpoint to be marked as unhealthy. If no value is specified, it uses the default value of 3. From 3eb17204d8b8234d2e5cc3e6be74c9e3e52f752e Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Fri, 2 Aug 2019 15:40:28 -0700 Subject: [PATCH 3/3] Finishing up --- .../resource_arm_traffic_manager_profile.go | 27 ++++-- ...source_arm_traffic_manager_profile_test.go | 91 ++++++++++++++++++- .../r/traffic_manager_profile.html.markdown | 6 +- 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/azurerm/resource_arm_traffic_manager_profile.go b/azurerm/resource_arm_traffic_manager_profile.go index e3c1c4a4fe39..d7c14bf18c39 100644 --- a/azurerm/resource_arm_traffic_manager_profile.go +++ b/azurerm/resource_arm_traffic_manager_profile.go @@ -161,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), } @@ -248,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 { @@ -261,10 +272,10 @@ 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{}) @@ -275,6 +286,10 @@ func expandArmTrafficManagerMonitorConfig(d *schema.ResourceData) *trafficmanage timeout := int64(monitor["timeout_in_seconds"].(int)) tolerated := int64(monitor["tolerated_number_of_failures"].(int)) + 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, @@ -282,7 +297,7 @@ func expandArmTrafficManagerMonitorConfig(d *schema.ResourceData) *trafficmanage IntervalInSeconds: &interval, TimeoutInSeconds: &timeout, ToleratedNumberOfFailures: &tolerated, - } + }, nil } func expandArmTrafficManagerDNSConfig(d *schema.ResourceData) *trafficmanager.DNSConfig { diff --git a/azurerm/resource_arm_traffic_manager_profile_test.go b/azurerm/resource_arm_traffic_manager_profile_test.go index 73d4c23e8ef6..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" @@ -324,10 +325,6 @@ func TestAccAzureRMTrafficManagerProfile_fastEndpointFailoverSettings(t *testing Config: testAccAzureRMTrafficManagerProfile_failover(rInt, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMTrafficManagerProfileExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "monitor_config.#", "1"), - resource.TestCheckResourceAttr(resourceName, "monitor_config.3418284669.interval_in_seconds", "30"), - resource.TestCheckResourceAttr(resourceName, "monitor_config.3418284669.timeout_in_seconds", "6"), - resource.TestCheckResourceAttr(resourceName, "monitor_config.3418284669.tolerated_number_of_failures", "3"), ), }, { @@ -335,6 +332,34 @@ func TestAccAzureRMTrafficManagerProfile_fastEndpointFailoverSettings(t *testing 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`"), + }, }, }) } @@ -635,3 +660,61 @@ resource "azurerm_traffic_manager_profile" "test" { } `, 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/website/docs/r/traffic_manager_profile.html.markdown b/website/docs/r/traffic_manager_profile.html.markdown index e94a9a9bb9ac..4b1f03553c14 100644 --- a/website/docs/r/traffic_manager_profile.html.markdown +++ b/website/docs/r/traffic_manager_profile.html.markdown @@ -100,11 +100,11 @@ 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` seconds (normal probing) and `10` seconds (fast probing). If no values are provided, the profile sets to a default value of `30` seconds. +* `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 the Probing Interval is set to `30` seconds, then you can set the Timeout value between `5` and `10` seconds. If no value is specified, it uses a default value of `10` seconds. If the Probing Interval is set to `10` seconds, then you can set the Timeout value between `5` and `9` seconds. If no Timeout value is specified, it uses a default value of `9` seconds. +* `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. Its value can range between 0 and 9. A value of 0 means a single monitoring failure can cause that endpoint to be marked as unhealthy. If no value is specified, it uses the default value of 3. +* `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