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

Traffic Manager: support for Geographically routed endpoints #986

Merged
merged 3 commits into from
Mar 16, 2018
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
96 changes: 56 additions & 40 deletions azurerm/resource_arm_traffic_manager_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ func resourceArmTrafficManagerEndpoint() *schema.Resource {
ForceNew: true,
},

"profile_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"resource_group_name": resourceGroupNameDiffSuppressSchema(),

"type": {
Type: schema.TypeString,
Required: true,
Expand All @@ -39,12 +47,6 @@ func resourceArmTrafficManagerEndpoint() *schema.Resource {
}, false),
},

"profile_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"target": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -96,21 +98,30 @@ func resourceArmTrafficManagerEndpoint() *schema.Resource {
Optional: true,
},

"resource_group_name": resourceGroupNameDiffSuppressSchema(),
"geo_mappings": {
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
},

"endpoint_monitor_status": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceArmTrafficManagerEndpointCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).trafficManagerEndpointsClient

log.Printf("[INFO] preparing arguments for ARM TrafficManager Endpoint creation.")
log.Printf("[INFO] preparing arguments for TrafficManager Endpoint creation.")

name := d.Get("name").(string)
endpointType := d.Get("type").(string)
fullEndpointType := fmt.Sprintf("Microsoft.Network/TrafficManagerProfiles/%s", endpointType)
profileName := d.Get("profile_name").(string)
resGroup := d.Get("resource_group_name").(string)
resourceGroup := d.Get("resource_group_name").(string)

params := trafficmanager.Endpoint{
Name: &name,
Expand All @@ -119,17 +130,17 @@ func resourceArmTrafficManagerEndpointCreate(d *schema.ResourceData, meta interf
}

ctx := meta.(*ArmClient).StopContext
_, err := client.CreateOrUpdate(ctx, resGroup, profileName, endpointType, name, params)
_, err := client.CreateOrUpdate(ctx, resourceGroup, profileName, endpointType, name, params)
if err != nil {
return err
}

read, err := client.Get(ctx, resGroup, profileName, endpointType, name)
read, err := client.Get(ctx, resourceGroup, profileName, endpointType, name)
if err != nil {
return err
}
if read.ID == nil {
return fmt.Errorf("Cannot read TrafficManager endpoint %s (resource group %s) ID", name, resGroup)
return fmt.Errorf("Cannot read Traffic Manager Endpoint %q (Resource Group %q) ID", name, resourceGroup)
}

d.SetId(*read.ID)
Expand All @@ -155,8 +166,6 @@ func resourceArmTrafficManagerEndpointRead(d *schema.ResourceData, meta interfac
}
}
profileName := id.Path["trafficManagerProfiles"]

// endpoint name is keyed by endpoint type in ARM ID
name := id.Path[endpointType]

ctx := meta.(*ArmClient).StopContext
Expand All @@ -166,23 +175,25 @@ func resourceArmTrafficManagerEndpointRead(d *schema.ResourceData, meta interfac
d.SetId("")
return nil
}
return fmt.Errorf("Error making Read request on TrafficManager Endpoint %s: %+v", name, err)
return fmt.Errorf("Error making Read request on TrafficManager Endpoint %q (Resource Group %q): %+v", name, resGroup, err)
}

endpoint := *resp.EndpointProperties

d.Set("resource_group_name", resGroup)
d.Set("name", resp.Name)
d.Set("type", endpointType)
d.Set("profile_name", profileName)
d.Set("endpoint_status", string(endpoint.EndpointStatus))
d.Set("target_resource_id", endpoint.TargetResourceID)
d.Set("target", endpoint.Target)
d.Set("weight", endpoint.Weight)
d.Set("priority", endpoint.Priority)
d.Set("endpoint_location", endpoint.EndpointLocation)
d.Set("endpoint_monitor_status", endpoint.EndpointMonitorStatus)
d.Set("min_child_endpoints", endpoint.MinChildEndpoints)

if props := resp.EndpointProperties; props != nil {
d.Set("endpoint_status", string(props.EndpointStatus))
d.Set("target_resource_id", props.TargetResourceID)
d.Set("target", props.Target)
d.Set("weight", props.Weight)
d.Set("priority", props.Priority)
d.Set("endpoint_location", props.EndpointLocation)
d.Set("endpoint_monitor_status", props.EndpointMonitorStatus)
d.Set("min_child_endpoints", props.MinChildEndpoints)
d.Set("geo_mappings", props.GeoMapping)
}

return nil
}
Expand Down Expand Up @@ -214,32 +225,37 @@ func resourceArmTrafficManagerEndpointDelete(d *schema.ResourceData, meta interf
}

func getArmTrafficManagerEndpointProperties(d *schema.ResourceData) *trafficmanager.EndpointProperties {
var endpointProps trafficmanager.EndpointProperties
target := d.Get("target").(string)
status := d.Get("endpoint_status").(string)

if targetResID := d.Get("target_resource_id").(string); targetResID != "" {
endpointProps.TargetResourceID = &targetResID
endpointProps := trafficmanager.EndpointProperties{
Target: &target,
EndpointStatus: trafficmanager.EndpointStatus(status),
}

if target := d.Get("target").(string); target != "" {
endpointProps.Target = &target
if resourceId := d.Get("target_resource_id").(string); resourceId != "" {
endpointProps.TargetResourceID = utils.String(resourceId)
}

if status := d.Get("endpoint_status").(string); status != "" {
endpointProps.EndpointStatus = trafficmanager.EndpointStatus(status)
if location := d.Get("endpoint_location").(string); location != "" {
endpointProps.EndpointLocation = utils.String(location)
}

if weight := d.Get("weight").(int); weight != 0 {
w64 := int64(weight)
endpointProps.Weight = &w64
inputMappings := d.Get("geo_mappings").([]interface{})
geoMappings := make([]string, 0)
for _, v := range inputMappings {
geoMappings = append(geoMappings, v.(string))
}
if len(geoMappings) > 0 {
endpointProps.GeoMapping = &geoMappings
}

if priority := d.Get("priority").(int); priority != 0 {
p64 := int64(priority)
endpointProps.Priority = &p64
if weight := d.Get("weight").(int); weight != 0 {
endpointProps.Weight = utils.Int64(int64(weight))
}

if location := d.Get("endpoint_location").(string); location != "" {
endpointProps.EndpointLocation = &location
if priority := d.Get("priority").(int); priority != 0 {
endpointProps.Priority = utils.Int64(int64(priority))
}

if minChildEndpoints := d.Get("min_child_endpoints").(int); minChildEndpoints != 0 {
Expand Down
112 changes: 112 additions & 0 deletions azurerm/resource_arm_traffic_manager_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,40 @@ func TestAccAzureRMTrafficManagerEndpoint_location(t *testing.T) {
})
}

func TestAccAzureRMTrafficManagerEndpoint_withGeoMappings(t *testing.T) {
resourceName := "azurerm_traffic_manager_endpoint.test"
ri := acctest.RandInt()
location := testLocation()
first := testAccAzureRMTrafficManagerEndpoint_geoMappings(ri, location)
second := testAccAzureRMTrafficManagerEndpoint_geoMappingsUpdated(ri, location)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMTrafficManagerEndpointDestroy,
Steps: []resource.TestStep{
{
Config: first,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMTrafficManagerEndpointExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "geo_mappings.#", "2"),
resource.TestCheckResourceAttr(resourceName, "geo_mappings.0", "GB"),
resource.TestCheckResourceAttr(resourceName, "geo_mappings.1", "FR"),
),
},
{
Config: second,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMTrafficManagerEndpointExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "geo_mappings.#", "2"),
resource.TestCheckResourceAttr(resourceName, "geo_mappings.0", "FR"),
resource.TestCheckResourceAttr(resourceName, "geo_mappings.1", "DE"),
),
},
},
})
}

func testCheckAzureRMTrafficManagerEndpointExists(name 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 @@ -716,3 +750,81 @@ resource "azurerm_traffic_manager_endpoint" "test" {
}
`, rInt, location, rInt, rInt, rInt)
}

func testAccAzureRMTrafficManagerEndpoint_geoMappings(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 = "Geographic"

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

monitor_config {
protocol = "http"
port = 80
path = "/"
}

tags {
environment = "Production"
}
}

resource "azurerm_traffic_manager_endpoint" "test" {
name = "example.com"
resource_group_name = "${azurerm_resource_group.test.name}"
profile_name = "${azurerm_traffic_manager_profile.test.name}"
target = "example.com"
type = "externalEndpoints"
geo_mappings = ["GB", "FR"]
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMTrafficManagerEndpoint_geoMappingsUpdated(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 = "Geographic"

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

monitor_config {
protocol = "http"
port = 80
path = "/"
}

tags {
environment = "Production"
}
}

resource "azurerm_traffic_manager_endpoint" "test" {
name = "example.com"
resource_group_name = "${azurerm_resource_group.test.name}"
profile_name = "${azurerm_traffic_manager_profile.test.name}"
target = "example.com"
type = "externalEndpoints"
geo_mappings = ["FR", "DE"]
}
`, rInt, location, rInt, rInt)
}
3 changes: 2 additions & 1 deletion azurerm/resource_arm_traffic_manager_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ func resourceArmTrafficManagerProfile() *schema.Resource {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(trafficmanager.Performance),
string(trafficmanager.Geographic),
string(trafficmanager.Weighted),
string(trafficmanager.Performance),
string(trafficmanager.Priority),
}, false),
},
Expand Down
47 changes: 47 additions & 0 deletions azurerm/resource_arm_traffic_manager_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,27 @@ func getTrafficManagerFQDN(hostname string) (string, error) {
return fmt.Sprintf("%s.%s", hostname, dnsSuffix), nil
}

func TestAccAzureRMTrafficManagerProfile_geographic(t *testing.T) {
resourceName := "azurerm_traffic_manager_profile.test"
ri := acctest.RandInt()
config := testAccAzureRMTrafficManagerProfile_geographic(ri, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMTrafficManagerProfileDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMTrafficManagerProfileExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "traffic_routing_method", "Geographic"),
),
},
},
})
}

func TestAccAzureRMTrafficManagerProfile_weighted(t *testing.T) {
resourceName := "azurerm_traffic_manager_profile.test"
ri := acctest.RandInt()
Expand Down Expand Up @@ -216,6 +237,32 @@ func testCheckAzureRMTrafficManagerProfileDestroy(s *terraform.State) error {
return nil
}

func testAccAzureRMTrafficManagerProfile_geographic(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 = "Geographic"

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

monitor_config {
protocol = "https"
port = 443
path = "/"
}
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMTrafficManagerProfile_weighted(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down
Loading