From 645a8a411cc2381cc166a97e4ad314e2b315d7ae Mon Sep 17 00:00:00 2001 From: bastard Date: Sun, 10 Jan 2016 14:09:05 +0000 Subject: [PATCH 1/4] Adding "named_port" support to Google's instance_group_manager. This allows HTTP and HTTPs load-balancers to direct traffic to ports other than tcp/80 and tcp/443. --- ...resource_compute_instance_group_manager.go | 103 ++++++++++++++++++ ...rce_compute_instance_group_manager_test.go | 12 ++ ...mpute_instance_group_manager.html.markdown | 12 ++ 3 files changed, 127 insertions(+) diff --git a/builtin/providers/google/resource_compute_instance_group_manager.go b/builtin/providers/google/resource_compute_instance_group_manager.go index 25a1ced5071d..6e1cefed8145 100644 --- a/builtin/providers/google/resource_compute_instance_group_manager.go +++ b/builtin/providers/google/resource_compute_instance_group_manager.go @@ -53,6 +53,25 @@ func resourceComputeInstanceGroupManager() *schema.Resource { Required: true, }, + "named_port": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + "update_strategy": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -118,6 +137,29 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte manager.TargetPools = s } + // Prepare the list of named ports + namedPortsCount := d.Get("named_port.#").(int) + + var namedPorts []*compute.NamedPort + + if namedPortsCount > 0 { + // Build up the list of namedPorts + namedPorts = make([]*compute.NamedPort, 0, namedPortsCount) + for i := 0; i < namedPortsCount; i++ { + prefix := fmt.Sprintf("named_port.%d", i) + + // Build a namedPort + namedPort := compute.NamedPort{ + Name: d.Get(prefix + ".name").(string), + Port: int64(d.Get(prefix + ".port").(int)), + } + + // Add it to the list of namedPorts + namedPorts = append(namedPorts, &namedPort) + } + manager.NamedPorts = namedPorts + } + updateStrategy := d.Get("update_strategy").(string) if !(updateStrategy == "NONE" || updateStrategy == "RESTART") { return fmt.Errorf("Update strategy must be \"NONE\" or \"RESTART\"") @@ -165,6 +207,22 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf d.Set("target_size", manager.TargetSize) d.Set("self_link", manager.SelfLink) + // Prepare the list of named ports + namedPortsCount := d.Get("named_port.#").(int) + + namedPorts := make([]map[string]interface{}, 0, 1) + if namedPortsCount > 0 { + for _, namedPort := range manager.NamedPorts { + + named_port := make(map[string]interface{}) + named_port["name"] = namedPort.Name + named_port["port"] = namedPort.Port + + namedPorts = append(namedPorts, named_port) + } + } + d.Set("named_port", namedPorts) + return nil } func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error { @@ -253,6 +311,51 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte d.SetPartial("instance_template") } + // If named_port changes then update + if d.HasChange("named_port") { + + // Prepare the list of named ports + namedPortsCount := d.Get("named_port.#").(int) + + var namedPorts []*compute.NamedPort + + if namedPortsCount > 0 { + // Build up the list of namedPorts + namedPorts = make([]*compute.NamedPort, 0, namedPortsCount) + for i := 0; i < namedPortsCount; i++ { + prefix := fmt.Sprintf("named_port.%d", i) + + // Build a namedPort + namedPort := compute.NamedPort{ + Name: d.Get(prefix + ".name").(string), + Port: int64(d.Get(prefix + ".port").(int)), + } + + // Add it to the list of namedPorts + namedPorts = append(namedPorts, &namedPort) + } + } + + // Build the parameter + setNamedPorts := &compute.InstanceGroupsSetNamedPortsRequest{ + NamedPorts: namedPorts, + } + + op, err := config.clientCompute.InstanceGroups.SetNamedPorts( + config.Project, d.Get("zone").(string), d.Id(), setNamedPorts).Do() + if err != nil { + return fmt.Errorf("Error updating InstanceGroupManager: %s", err) + } + + // Wait for the operation to complete + err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") + if err != nil { + return err + } + + d.SetPartial("named_port") + } + // If size changes trigger a resize if d.HasChange("target_size") { if v, ok := d.GetOk("target_size"); ok { diff --git a/builtin/providers/google/resource_compute_instance_group_manager_test.go b/builtin/providers/google/resource_compute_instance_group_manager_test.go index f7f2c147cc3d..eb8606bcc534 100644 --- a/builtin/providers/google/resource_compute_instance_group_manager_test.go +++ b/builtin/providers/google/resource_compute_instance_group_manager_test.go @@ -252,6 +252,10 @@ func testAccInstanceGroupManager_update(template, target, igm string) string { base_instance_name = "igm-update" zone = "us-central1-c" target_size = 2 + named_port { + name = "customHTTP" + port = 8888 + } }`, template, target, igm) } @@ -322,5 +326,13 @@ func testAccInstanceGroupManager_update2(template1, target, template2, igm strin base_instance_name = "igm-update" zone = "us-central1-c" target_size = 3 + named_port { + name = "customHTTP" + port = 8888 + } + named_port { + name = "customHTTPs" + port = 8889 + } }`, template1, target, template2, igm) } diff --git a/website/source/docs/providers/google/r/compute_instance_group_manager.html.markdown b/website/source/docs/providers/google/r/compute_instance_group_manager.html.markdown index 8bc6c1500606..8d87a13f2446 100644 --- a/website/source/docs/providers/google/r/compute_instance_group_manager.html.markdown +++ b/website/source/docs/providers/google/r/compute_instance_group_manager.html.markdown @@ -25,6 +25,12 @@ resource "google_compute_instance_group_manager" "foobar" { base_instance_name = "foobar" zone = "us-central1-a" target_size = 2 + + named_port { + name = "customHTTP" + port = 8888 + } + } ``` @@ -63,6 +69,12 @@ affect existing instances. * `zone` - (Required) The zone that instances in this group should be created in. +The `named_port` block supports: (Include a named_port block for each named-port required). + +* `name` - (Required) The name of the port. + +* `port` - (Required) The port number. + ## Attributes Reference The following attributes are exported: From 4114c31c00e674d47f32ef85a70b08212ea3d452 Mon Sep 17 00:00:00 2001 From: "Chris H (CruftMaster)" Date: Sun, 17 Jan 2016 17:40:46 +0000 Subject: [PATCH 2/4] Bringing into line with https://github.com/hashicorp/terraform/pull/4087 --- ...resource_compute_instance_group_manager.go | 86 +++++-------------- 1 file changed, 22 insertions(+), 64 deletions(-) diff --git a/builtin/providers/google/resource_compute_instance_group_manager.go b/builtin/providers/google/resource_compute_instance_group_manager.go index 6e1cefed8145..df88a9639288 100644 --- a/builtin/providers/google/resource_compute_instance_group_manager.go +++ b/builtin/providers/google/resource_compute_instance_group_manager.go @@ -107,6 +107,18 @@ func resourceComputeInstanceGroupManager() *schema.Resource { } } +func getNamedPorts(nps []interface{}) []*compute.NamedPort { + namedPorts := make([]*compute.NamedPort, 0, len(nps)) + for _, v := range nps { + np := v.(map[string]interface{}) + namedPorts = append(namedPorts, &compute.NamedPort{ + Name: np["name"].(string), + Port: int64(np["port"].(int)), + }) + } + return namedPorts +} + func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -129,6 +141,10 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte manager.Description = v.(string) } + if v, ok := d.GetOk("named_port"); ok { + manager.NamedPorts = getNamedPorts(v.([]interface{})) + } + if attr := d.Get("target_pools").(*schema.Set); attr.Len() > 0 { var s []string for _, v := range attr.List() { @@ -137,29 +153,6 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte manager.TargetPools = s } - // Prepare the list of named ports - namedPortsCount := d.Get("named_port.#").(int) - - var namedPorts []*compute.NamedPort - - if namedPortsCount > 0 { - // Build up the list of namedPorts - namedPorts = make([]*compute.NamedPort, 0, namedPortsCount) - for i := 0; i < namedPortsCount; i++ { - prefix := fmt.Sprintf("named_port.%d", i) - - // Build a namedPort - namedPort := compute.NamedPort{ - Name: d.Get(prefix + ".name").(string), - Port: int64(d.Get(prefix + ".port").(int)), - } - - // Add it to the list of namedPorts - namedPorts = append(namedPorts, &namedPort) - } - manager.NamedPorts = namedPorts - } - updateStrategy := d.Get("update_strategy").(string) if !(updateStrategy == "NONE" || updateStrategy == "RESTART") { return fmt.Errorf("Update strategy must be \"NONE\" or \"RESTART\"") @@ -202,27 +195,12 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf } // Set computed fields + d.Set("named_port", manager.NamedPorts) d.Set("fingerprint", manager.Fingerprint) d.Set("instance_group", manager.InstanceGroup) d.Set("target_size", manager.TargetSize) d.Set("self_link", manager.SelfLink) - // Prepare the list of named ports - namedPortsCount := d.Get("named_port.#").(int) - - namedPorts := make([]map[string]interface{}, 0, 1) - if namedPortsCount > 0 { - for _, namedPort := range manager.NamedPorts { - - named_port := make(map[string]interface{}) - named_port["name"] = namedPort.Name - named_port["port"] = namedPort.Port - - namedPorts = append(namedPorts, named_port) - } - } - d.Set("named_port", namedPorts) - return nil } func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error { @@ -311,43 +289,23 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte d.SetPartial("instance_template") } - // If named_port changes then update + // If named_port changes then update: if d.HasChange("named_port") { - // Prepare the list of named ports - namedPortsCount := d.Get("named_port.#").(int) - - var namedPorts []*compute.NamedPort - - if namedPortsCount > 0 { - // Build up the list of namedPorts - namedPorts = make([]*compute.NamedPort, 0, namedPortsCount) - for i := 0; i < namedPortsCount; i++ { - prefix := fmt.Sprintf("named_port.%d", i) - - // Build a namedPort - namedPort := compute.NamedPort{ - Name: d.Get(prefix + ".name").(string), - Port: int64(d.Get(prefix + ".port").(int)), - } - - // Add it to the list of namedPorts - namedPorts = append(namedPorts, &namedPort) - } - } - - // Build the parameter + // Build the parameters for a "SetNamedPorts" request: + namedPorts := getNamedPorts(d.Get("named_port").([]interface{})) setNamedPorts := &compute.InstanceGroupsSetNamedPortsRequest{ NamedPorts: namedPorts, } + // Make the request: op, err := config.clientCompute.InstanceGroups.SetNamedPorts( config.Project, d.Get("zone").(string), d.Id(), setNamedPorts).Do() if err != nil { return fmt.Errorf("Error updating InstanceGroupManager: %s", err) } - // Wait for the operation to complete + // Wait for the operation to complete: err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") if err != nil { return err From e08da4c1ef6c9f8079ea2f4e570fe92d408bc310 Mon Sep 17 00:00:00 2001 From: "Chris H (CruftMaster)" Date: Wed, 20 Jan 2016 08:18:36 +0000 Subject: [PATCH 3/4] Including test and updatetest --- ...rce_compute_instance_group_manager_test.go | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/builtin/providers/google/resource_compute_instance_group_manager_test.go b/builtin/providers/google/resource_compute_instance_group_manager_test.go index eb8606bcc534..74a70e33694c 100644 --- a/builtin/providers/google/resource_compute_instance_group_manager_test.go +++ b/builtin/providers/google/resource_compute_instance_group_manager_test.go @@ -55,6 +55,10 @@ func TestAccInstanceGroupManager_update(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckInstanceGroupManagerExists( "google_compute_instance_group_manager.igm-update", &manager), + testAccCheckInstanceGroupManagerNamedPorts( + "google_compute_instance_group_manager.igm-update", + map[string]int64{"customHTTP": 8080}, + &manager), ), }, resource.TestStep{ @@ -65,6 +69,10 @@ func TestAccInstanceGroupManager_update(t *testing.T) { testAccCheckInstanceGroupManagerUpdated( "google_compute_instance_group_manager.igm-update", 3, "google_compute_target_pool.igm-update", template2), + testAccCheckInstanceGroupManagerNamedPorts( + "google_compute_instance_group_manager.igm-update", + map[string]int64{"customHTTP": 8080, "customHTTPs": 8443}, + &manager), ), }, }, @@ -157,6 +165,42 @@ func testAccCheckInstanceGroupManagerUpdated(n string, size int64, targetPool st } } +func testAccCheckInstanceGroupManagerNamedPorts(n string, np map[string]int64, instanceGroupManager *compute.InstanceGroupManager) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + + manager, err := config.clientCompute.InstanceGroupManagers.Get( + config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do() + if err != nil { + return err + } + + var found bool + for _, namedPort := range manager.NamedPorts { + found = false + for name, port := range np { + if namedPort.Name == name && namedPort.Port == port { + found = true + } + } + if !found { + return fmt.Errorf("named port incorrect") + } + } + + return nil + } +} + func testAccInstanceGroupManager_basic(template, target, igm1, igm2 string) string { return fmt.Sprintf(` resource "google_compute_instance_template" "igm-basic" { @@ -254,7 +298,7 @@ func testAccInstanceGroupManager_update(template, target, igm string) string { target_size = 2 named_port { name = "customHTTP" - port = 8888 + port = 8080 } }`, template, target, igm) } @@ -328,11 +372,11 @@ func testAccInstanceGroupManager_update2(template1, target, template2, igm strin target_size = 3 named_port { name = "customHTTP" - port = 8888 + port = 8080 } named_port { name = "customHTTPs" - port = 8889 + port = 8443 } }`, template1, target, template2, igm) } From 05088f8934825b7ac0c6473da8e5659787649e7c Mon Sep 17 00:00:00 2001 From: "Chris H (CruftMaster)" Date: Wed, 20 Jan 2016 09:05:04 +0000 Subject: [PATCH 4/4] Upper-case port-names aren't allowed by Google's API --- .../resource_compute_instance_group_manager_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/builtin/providers/google/resource_compute_instance_group_manager_test.go b/builtin/providers/google/resource_compute_instance_group_manager_test.go index 74a70e33694c..c0b466b7eaaf 100644 --- a/builtin/providers/google/resource_compute_instance_group_manager_test.go +++ b/builtin/providers/google/resource_compute_instance_group_manager_test.go @@ -57,7 +57,7 @@ func TestAccInstanceGroupManager_update(t *testing.T) { "google_compute_instance_group_manager.igm-update", &manager), testAccCheckInstanceGroupManagerNamedPorts( "google_compute_instance_group_manager.igm-update", - map[string]int64{"customHTTP": 8080}, + map[string]int64{"customhttp": 8080}, &manager), ), }, @@ -71,7 +71,7 @@ func TestAccInstanceGroupManager_update(t *testing.T) { "google_compute_target_pool.igm-update", template2), testAccCheckInstanceGroupManagerNamedPorts( "google_compute_instance_group_manager.igm-update", - map[string]int64{"customHTTP": 8080, "customHTTPs": 8443}, + map[string]int64{"customhttp": 8080, "customhttps": 8443}, &manager), ), }, @@ -297,7 +297,7 @@ func testAccInstanceGroupManager_update(template, target, igm string) string { zone = "us-central1-c" target_size = 2 named_port { - name = "customHTTP" + name = "customhttp" port = 8080 } }`, template, target, igm) @@ -371,11 +371,11 @@ func testAccInstanceGroupManager_update2(template1, target, template2, igm strin zone = "us-central1-c" target_size = 3 named_port { - name = "customHTTP" + name = "customhttp" port = 8080 } named_port { - name = "customHTTPs" + name = "customhttps" port = 8443 } }`, template1, target, template2, igm)