From 07e7bd9b9165995a828a01a8b2699359f3006dd3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 12 Nov 2018 07:29:18 +1100 Subject: [PATCH 1/2] Add steering policy support to load balancer Updates `cloudflare_load_balancer` to support the steering policy attribute to determine how the load balancer routes to the origin. Fixes #146. --- .../resource_cloudflare_load_balancer.go | 32 ++++++++++++------- .../resource_cloudflare_load_balancer_test.go | 7 +++- website/docs/r/load_balancer.html.markdown | 2 ++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/cloudflare/resource_cloudflare_load_balancer.go b/cloudflare/resource_cloudflare_load_balancer.go index e7d963b7e5..da1d9eba09 100644 --- a/cloudflare/resource_cloudflare_load_balancer.go +++ b/cloudflare/resource_cloudflare_load_balancer.go @@ -77,6 +77,13 @@ func resourceCloudflareLoadBalancer() *schema.Resource { ValidateFunc: validation.StringLenBetween(0, 1024), }, + "steering_policy": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"off", "geo", "dynamic_latency", ""}, false), + Default: "", + }, + // nb enterprise only "pop_pools": { Type: schema.TypeSet, @@ -152,11 +159,12 @@ func resourceCloudflareLoadBalancerCreate(d *schema.ResourceData, meta interface client := meta.(*cloudflare.API) newLoadBalancer := cloudflare.LoadBalancer{ - Name: d.Get("name").(string), - FallbackPool: d.Get("fallback_pool_id").(string), - DefaultPools: expandInterfaceToStringList(d.Get("default_pool_ids")), - Proxied: d.Get("proxied").(bool), - TTL: d.Get("ttl").(int), + Name: d.Get("name").(string), + FallbackPool: d.Get("fallback_pool_id").(string), + DefaultPools: expandInterfaceToStringList(d.Get("default_pool_ids")), + Proxied: d.Get("proxied").(bool), + TTL: d.Get("ttl").(int), + SteeringPolicy: d.Get("steering_policy").(string), } if description, ok := d.GetOk("description"); ok { @@ -214,12 +222,13 @@ func resourceCloudflareLoadBalancerUpdate(d *schema.ResourceData, meta interface zoneId := d.Get("zone_id").(string) loadBalancer := cloudflare.LoadBalancer{ - ID: d.Id(), - Name: d.Get("name").(string), - FallbackPool: d.Get("fallback_pool_id").(string), - DefaultPools: expandInterfaceToStringList(d.Get("default_pool_ids")), - Proxied: d.Get("proxied").(bool), - TTL: d.Get("ttl").(int), + ID: d.Id(), + Name: d.Get("name").(string), + FallbackPool: d.Get("fallback_pool_id").(string), + DefaultPools: expandInterfaceToStringList(d.Get("default_pool_ids")), + Proxied: d.Get("proxied").(bool), + TTL: d.Get("ttl").(int), + SteeringPolicy: d.Get("steering_policy").(string), } if description, ok := d.GetOk("description"); ok { @@ -289,6 +298,7 @@ func resourceCloudflareLoadBalancerRead(d *schema.ResourceData, meta interface{} d.Set("proxied", loadBalancer.Proxied) d.Set("description", loadBalancer.Description) d.Set("ttl", loadBalancer.TTL) + d.Set("steering_policy", loadBalancer.SteeringPolicy) d.Set("created_on", loadBalancer.CreatedOn.Format(time.RFC3339Nano)) d.Set("modified_on", loadBalancer.ModifiedOn.Format(time.RFC3339Nano)) diff --git a/cloudflare/resource_cloudflare_load_balancer_test.go b/cloudflare/resource_cloudflare_load_balancer_test.go index 3a549685b2..c258a51858 100644 --- a/cloudflare/resource_cloudflare_load_balancer_test.go +++ b/cloudflare/resource_cloudflare_load_balancer_test.go @@ -9,11 +9,12 @@ import ( "os" + "regexp" + "github.com/cloudflare/cloudflare-go" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "regexp" ) func TestAccCloudflareLoadBalancer_Basic(t *testing.T) { @@ -43,6 +44,7 @@ func TestAccCloudflareLoadBalancer_Basic(t *testing.T) { testAccCheckCloudflareLoadBalancerDates(name, &loadBalancer, testStartTime), resource.TestCheckResourceAttr(name, "proxied", "false"), // default value resource.TestCheckResourceAttr(name, "ttl", "30"), + resource.TestCheckResourceAttr(name, "steering_policy", ""), ), }, }, @@ -70,6 +72,7 @@ func TestAccCloudflareLoadBalancer_GeoBalanced(t *testing.T) { resource.TestCheckResourceAttr(name, "description", "tf-acctest load balancer using geo-balancing"), resource.TestCheckResourceAttr(name, "proxied", "true"), resource.TestCheckResourceAttr(name, "ttl", "0"), + resource.TestCheckResourceAttr(name, "steering_policy", "geo"), resource.TestCheckResourceAttr(name, "pop_pools.#", "1"), resource.TestCheckResourceAttr(name, "region_pools.#", "1"), ), @@ -294,6 +297,7 @@ func testAccCheckCloudflareLoadBalancerConfigBasic(zone, id string) string { resource "cloudflare_load_balancer" "%[2]s" { zone = "%[1]s" name = "tf-testacc-lb-%[2]s" + steering_policy = "" fallback_pool_id = "${cloudflare_load_balancer_pool.%[2]s.id}" default_pool_ids = ["${cloudflare_load_balancer_pool.%[2]s.id}"] }`, zone, id) @@ -308,6 +312,7 @@ resource "cloudflare_load_balancer" "%[2]s" { default_pool_ids = ["${cloudflare_load_balancer_pool.%[2]s.id}"] description = "tf-acctest load balancer using geo-balancing" proxied = true // can't set ttl with proxied + steering_policy = "geo" pop_pools { pop = "LAX" pool_ids = ["${cloudflare_load_balancer_pool.%[2]s.id}"] diff --git a/website/docs/r/load_balancer.html.markdown b/website/docs/r/load_balancer.html.markdown index 3d4c231d18..534e6bdfcb 100644 --- a/website/docs/r/load_balancer.html.markdown +++ b/website/docs/r/load_balancer.html.markdown @@ -23,6 +23,7 @@ resource "cloudflare_load_balancer" "bar" { default_pool_ids = ["${cloudflare_load_balancer_pool.foo.id}"] description = "example load balancer using geo-balancing" proxied = true + steering_policy = "geo" pop_pools { pop = "LAX" pool_ids = ["${cloudflare_load_balancer_pool.foo.id}"] @@ -53,6 +54,7 @@ The following arguments are supported: * `default_pool_ids` - (Required) A list of pool IDs ordered by their failover priority. Used whenever region/pop pools are not defined. * `description` - (Optional) Free text description. * `ttl` - (Optional) Time to live (TTL) of this load balancer's DNS `name`. Conflicts with `proxied` - this cannot be set for proxied load balancers. Default is `30`. +* `steering_policy` - (Optional) Determine which method the load balancer uses to determine the fastest route to your origin. Valid values are: "off", "geo", "dynamic_latency" or "". Default is "". * `proxied` - (Optional) Whether the hostname gets Cloudflare's origin protection. Defaults to `false`. * `region_pools` - (Optional) A set containing mappings of region/country codes to a list of pool IDs (ordered by their failover priority) for the given region. Fields documented below. * `pop_pools` - (Optional) A set containing mappings of Cloudflare Point-of-Presence (PoP) identifiers to a list of pool IDs (ordered by their failover priority) for the PoP (datacenter). This feature is only available to enterprise customers. Fields documented below. From fb46ba45cc74a743e6ea186e963805f082c1c256 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 12 Nov 2018 07:30:29 +1100 Subject: [PATCH 2/2] s/Id/ID to address go lint --- .../resource_cloudflare_load_balancer.go | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/cloudflare/resource_cloudflare_load_balancer.go b/cloudflare/resource_cloudflare_load_balancer.go index da1d9eba09..df1087beff 100644 --- a/cloudflare/resource_cloudflare_load_balancer.go +++ b/cloudflare/resource_cloudflare_load_balancer.go @@ -192,15 +192,15 @@ func resourceCloudflareLoadBalancerCreate(d *schema.ResourceData, meta interface } zoneName := d.Get("zone").(string) - zoneId, err := client.ZoneIDByName(zoneName) + zoneID, err := client.ZoneIDByName(zoneName) if err != nil { return fmt.Errorf("error finding zone %q: %s", zoneName, err) } - d.Set("zone_id", zoneId) + d.Set("zone_id", zoneID) log.Printf("[INFO] Creating Cloudflare Load Balancer from struct: %+v", newLoadBalancer) - r, err := client.CreateLoadBalancer(zoneId, newLoadBalancer) + r, err := client.CreateLoadBalancer(zoneID, newLoadBalancer) if err != nil { return errors.Wrap(err, "error creating load balancer for zone") } @@ -219,7 +219,7 @@ func resourceCloudflareLoadBalancerCreate(d *schema.ResourceData, meta interface func resourceCloudflareLoadBalancerUpdate(d *schema.ResourceData, meta interface{}) error { // since api only supports replace, update looks a lot like create... client := meta.(*cloudflare.API) - zoneId := d.Get("zone_id").(string) + zoneID := d.Get("zone_id").(string) loadBalancer := cloudflare.LoadBalancer{ ID: d.Id(), @@ -253,7 +253,7 @@ func resourceCloudflareLoadBalancerUpdate(d *schema.ResourceData, meta interface log.Printf("[INFO] Updating Cloudflare Load Balancer from struct: %+v", loadBalancer) - _, err := client.ModifyLoadBalancer(zoneId, loadBalancer) + _, err := client.ModifyLoadBalancer(zoneID, loadBalancer) if err != nil { return errors.Wrap(err, "error creating load balancer for zone") } @@ -279,18 +279,18 @@ func expandGeoPools(pool interface{}, geoType string) (map[string][]string, erro func resourceCloudflareLoadBalancerRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*cloudflare.API) - zoneId := d.Get("zone_id").(string) - loadBalancerId := d.Id() + zoneID := d.Get("zone_id").(string) + loadBalancerID := d.Id() - loadBalancer, err := client.LoadBalancerDetails(zoneId, loadBalancerId) + loadBalancer, err := client.LoadBalancerDetails(zoneID, loadBalancerID) if err != nil { if strings.Contains(err.Error(), "HTTP status 404") { - log.Printf("[INFO] Load balancer %s in zone %s not found", loadBalancerId, zoneId) + log.Printf("[INFO] Load balancer %s in zone %s not found", loadBalancerID, zoneID) d.SetId("") return nil } return errors.Wrap(err, - fmt.Sprintf("Error reading load balancer resource from API for resource %s in zone %s", zoneId, loadBalancerId)) + fmt.Sprintf("Error reading load balancer resource from API for resource %s in zone %s", zoneID, loadBalancerID)) } d.Set("name", loadBalancer.Name) @@ -331,12 +331,12 @@ func flattenGeoPools(pools map[string][]string, geoType string) *schema.Set { func resourceCloudflareLoadBalancerDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*cloudflare.API) - zoneId := d.Get("zone_id").(string) - loadBalancerId := d.Id() + zoneID := d.Get("zone_id").(string) + loadBalancerID := d.Id() - log.Printf("[INFO] Deleting Cloudflare Load Balancer: %s in zone: %s", loadBalancerId, zoneId) + log.Printf("[INFO] Deleting Cloudflare Load Balancer: %s in zone: %s", loadBalancerID, zoneID) - err := client.DeleteLoadBalancer(zoneId, loadBalancerId) + err := client.DeleteLoadBalancer(zoneID, loadBalancerID) if err != nil { return fmt.Errorf("error deleting Cloudflare Load Balancer: %s", err) } @@ -350,21 +350,21 @@ func resourceCloudflareLoadBalancerImport(d *schema.ResourceData, meta interface // split the id so we can lookup idAttr := strings.SplitN(d.Id(), "/", 2) var zoneName string - var loadBalancerId string + var loadBalancerID string if len(idAttr) == 2 { zoneName = idAttr[0] - loadBalancerId = idAttr[1] + loadBalancerID = idAttr[1] } else { - return nil, fmt.Errorf("invalid id (\"%s\") specified, should be in format \"zoneName/loadBalancerId\"", d.Id()) + return nil, fmt.Errorf("invalid id (\"%s\") specified, should be in format \"zoneName/loadBalancerID\"", d.Id()) } - zoneId, err := client.ZoneIDByName(zoneName) + zoneID, err := client.ZoneIDByName(zoneName) if err != nil { return nil, fmt.Errorf("error finding zoneName %q: %s", zoneName, err) } d.Set("zone", zoneName) - d.Set("zone_id", zoneId) - d.SetId(loadBalancerId) + d.Set("zone_id", zoneID) + d.SetId(loadBalancerID) return []*schema.ResourceData{d}, nil }