From 372788dc6353ff3638c071b776835f0660b1df4f Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Tue, 11 Jul 2017 15:10:22 -0700 Subject: [PATCH 1/2] Add support for auto_healing_policies to google_compute_instance_group_manager. --- ...resource_compute_instance_group_manager.go | 86 ++++++++++++- ...rce_compute_instance_group_manager_test.go | 116 ++++++++++++++++++ ...mpute_instance_group_manager.html.markdown | 12 ++ 3 files changed, 210 insertions(+), 4 deletions(-) diff --git a/google/resource_compute_instance_group_manager.go b/google/resource_compute_instance_group_manager.go index 7112fb036a6..9034b0b3e49 100644 --- a/google/resource_compute_instance_group_manager.go +++ b/google/resource_compute_instance_group_manager.go @@ -7,6 +7,7 @@ import ( "time" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" computeBeta "google.golang.org/api/compute/v0.beta" "google.golang.org/api/compute/v1" @@ -114,6 +115,27 @@ func resourceComputeInstanceGroupManager() *schema.Resource { Computed: true, Optional: true, }, + + "auto_healing_policies": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "health_check": &schema.Schema{ + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkRelativePaths, + }, + + "initial_delay_sec": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(0, 3600), + }, + }, + }, + }, }, } } @@ -145,9 +167,10 @@ func getNamedPortsBeta(nps []interface{}) []*computeBeta.NamedPort { } var InstanceGroupManagerBaseVersion = v1 +var InstanceGroupManagerVersionedFeatures = []Feature{Feature{Version: v0beta, Item: "auto_healing_policies"}} func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error { - computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseVersion, []Feature{}) + computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseVersion, InstanceGroupManagerVersionedFeatures) config := meta.(*Config) project, err := getProject(d, config) @@ -191,6 +214,10 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte return fmt.Errorf("Update strategy must be \"NONE\" or \"RESTART\"") } + if v, ok := d.GetOk("auto_healing_policies"); ok { + manager.AutoHealingPolicies = expandAutoHealingPolicies(v.([]interface{})) + } + log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager) var op interface{} switch computeApiVersion { @@ -243,7 +270,7 @@ func flattenNamedPortsBeta(namedPorts []*computeBeta.NamedPort) []map[string]int } func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interface{}) error { - computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseVersion, []Feature{}) + computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseVersion, InstanceGroupManagerVersionedFeatures) config := meta.(*Config) project, err := getProject(d, config) @@ -352,12 +379,13 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf update_strategy = "RESTART" } d.Set("update_strategy", update_strategy.(string)) + d.Set("auto_healing_policies", flattenAutoHealingPolicies(manager.AutoHealingPolicies)) return nil } func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error { - computeApiVersion := getComputeApiVersionUpdate(d, InstanceGroupManagerBaseVersion, []Feature{}, []Feature{}) + computeApiVersion := getComputeApiVersionUpdate(d, InstanceGroupManagerBaseVersion, InstanceGroupManagerVersionedFeatures, []Feature{}) config := meta.(*Config) project, err := getProject(d, config) @@ -607,13 +635,36 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte d.SetPartial("target_size") } + // We will always be in v0beta inside this conditional + if d.HasChange("auto_healing_policies") { + setAutoHealingPoliciesRequest := &computeBeta.InstanceGroupManagersSetAutoHealingRequest{} + if v, ok := d.GetOk("auto_healing_policies"); ok { + setAutoHealingPoliciesRequest.AutoHealingPolicies = expandAutoHealingPolicies(v.([]interface{})) + } + + op, err := config.clientComputeBeta.InstanceGroupManagers.SetAutoHealingPolicies( + project, d.Get("zone").(string), d.Id(), setAutoHealingPoliciesRequest).Do() + + if err != nil { + return fmt.Errorf("Error updating AutoHealingPolicies: %s", err) + } + + // Wait for the operation to complete + err = computeSharedOperationWaitZone(config, op, project, d.Get("zone").(string), "Updating AutoHealingPolicies") + if err != nil { + return err + } + + d.SetPartial("auto_healing_policies") + } + d.Partial(false) return resourceComputeInstanceGroupManagerRead(d, meta) } func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error { - computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseVersion, []Feature{}) + computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseVersion, InstanceGroupManagerVersionedFeatures) config := meta.(*Config) project, err := getProject(d, config) @@ -689,3 +740,30 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte d.SetId("") return nil } + +func expandAutoHealingPolicies(configured []interface{}) []*computeBeta.InstanceGroupManagerAutoHealingPolicy { + autoHealingPolicies := make([]*computeBeta.InstanceGroupManagerAutoHealingPolicy, 0, len(configured)) + for _, raw := range configured { + data := raw.(map[string]interface{}) + autoHealingPolicy := computeBeta.InstanceGroupManagerAutoHealingPolicy{ + HealthCheck: data["health_check"].(string), + InitialDelaySec: int64(data["initial_delay_sec"].(int)), + } + + autoHealingPolicies = append(autoHealingPolicies, &autoHealingPolicy) + } + return autoHealingPolicies +} + +func flattenAutoHealingPolicies(autoHealingPolicies []*computeBeta.InstanceGroupManagerAutoHealingPolicy) []map[string]interface{} { + autoHealingPoliciesSchema := make([]map[string]interface{}, 0, len(autoHealingPolicies)) + for _, autoHealingPolicy := range autoHealingPolicies { + data := map[string]interface{}{ + "health_check": autoHealingPolicy.HealthCheck, + "initial_delay_sec": autoHealingPolicy.InitialDelaySec, + } + + autoHealingPoliciesSchema = append(autoHealingPoliciesSchema, data) + } + return autoHealingPoliciesSchema +} diff --git a/google/resource_compute_instance_group_manager_test.go b/google/resource_compute_instance_group_manager_test.go index 22e35d1635e..617f2826d0b 100644 --- a/google/resource_compute_instance_group_manager_test.go +++ b/google/resource_compute_instance_group_manager_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + computeBeta "google.golang.org/api/compute/v0.beta" "google.golang.org/api/compute/v1" "github.com/hashicorp/terraform/helper/acctest" @@ -159,6 +160,43 @@ func TestAccInstanceGroupManager_separateRegions(t *testing.T) { }) } +func TestAccInstanceGroupManager_autoHealingPolicies(t *testing.T) { + var manager computeBeta.InstanceGroupManager + + template := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + target := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + igm := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + hck := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckInstanceGroupManagerDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccInstanceGroupManager_autoHealingPolicies(template, target, igm, hck), + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceGroupManagerBetaExists( + "google_compute_instance_group_manager.igm-basic", &manager), + ), + }, + }, + }) + + if len(manager.AutoHealingPolicies) != 1 { + t.Errorf("Expected # of auto healing policies to be 1, got %d", len(manager.AutoHealingPolicies)) + } + autoHealingPolicy := manager.AutoHealingPolicies[0] + + if !strings.Contains(autoHealingPolicy.HealthCheck, hck) { + t.Errorf("Expected string \"%s\" to appear in \"%s\"", hck, autoHealingPolicy.HealthCheck) + } + + if autoHealingPolicy.InitialDelaySec != 10 { + t.Errorf("Expected auto healing policy inital delay to be 10, got %d", autoHealingPolicy.InitialDelaySec) + } +} + func testAccCheckInstanceGroupManagerDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) @@ -205,6 +243,35 @@ func testAccCheckInstanceGroupManagerExists(n string, manager *compute.InstanceG } } +func testAccCheckInstanceGroupManagerBetaExists(n string, manager *computeBeta.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) + + found, err := config.clientComputeBeta.InstanceGroupManagers.Get( + config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do() + if err != nil { + return err + } + + if found.Name != rs.Primary.ID { + return fmt.Errorf("InstanceGroupManager not found") + } + + *manager = *found + + return nil + } +} + func testAccCheckInstanceGroupManagerUpdated(n string, size int64, targetPool string, template string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -646,3 +713,52 @@ func resourceSplitter(resource string) string { return splits[len(splits)-1] } + +func testAccInstanceGroupManager_autoHealingPolicies(template, target, igm, hck string) string { + return fmt.Sprintf(` + resource "google_compute_instance_template" "igm-basic" { + name = "%s" + machine_type = "n1-standard-1" + can_ip_forward = false + tags = ["foo", "bar"] + disk { + source_image = "debian-cloud/debian-8-jessie-v20160803" + auto_delete = true + boot = true + } + network_interface { + network = "default" + } + metadata { + foo = "bar" + } + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } + } + resource "google_compute_target_pool" "igm-basic" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + session_affinity = "CLIENT_IP_PROTO" + } + resource "google_compute_instance_group_manager" "igm-basic" { + description = "Terraform test instance group manager" + name = "%s" + instance_template = "${google_compute_instance_template.igm-basic.self_link}" + target_pools = ["${google_compute_target_pool.igm-basic.self_link}"] + base_instance_name = "igm-basic" + zone = "us-central1-c" + target_size = 2 + auto_healing_policies { + health_check = "${google_compute_http_health_check.zero.self_link}" + initial_delay_sec = "10" + } + } + resource "google_compute_http_health_check" "zero" { + name = "%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 + } + `, template, target, igm, hck) +} diff --git a/website/docs/r/compute_instance_group_manager.html.markdown b/website/docs/r/compute_instance_group_manager.html.markdown index b7d8c6cd910..5407a055810 100644 --- a/website/docs/r/compute_instance_group_manager.html.markdown +++ b/website/docs/r/compute_instance_group_manager.html.markdown @@ -82,12 +82,24 @@ The following arguments are supported: instances in the group are added. Updating the target pools attribute does not affect existing instances. +--- + +* `auto_healing_policies` - (Optional, Beta) The autohealing policies for this managed instance +group. You can specify only one value. Structure is documented below. + 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. +The `auto_healing_policies` block supports: + +* `health_check` - (Required) The health check that signals autohealing. + +* `initial_delay_sec` - (Required) The number of seconds that the managed instance group waits before + it applies autohealing policies to new instances or recently recreated instances. Between 0 and 3600. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are From 118df4343f89fc43f65db215ca997e9da2dc5b63 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Fri, 14 Jul 2017 11:30:45 -0700 Subject: [PATCH 2/2] Move test configuration above helper method. --- .../resource_compute_instance_group_manager_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/google/resource_compute_instance_group_manager_test.go b/google/resource_compute_instance_group_manager_test.go index 617f2826d0b..44e13e07772 100644 --- a/google/resource_compute_instance_group_manager_test.go +++ b/google/resource_compute_instance_group_manager_test.go @@ -708,12 +708,6 @@ func testAccInstanceGroupManager_separateRegions(igm1, igm2 string) string { `, igm1, igm2) } -func resourceSplitter(resource string) string { - splits := strings.Split(resource, "/") - - return splits[len(splits)-1] -} - func testAccInstanceGroupManager_autoHealingPolicies(template, target, igm, hck string) string { return fmt.Sprintf(` resource "google_compute_instance_template" "igm-basic" { @@ -762,3 +756,9 @@ func testAccInstanceGroupManager_autoHealingPolicies(template, target, igm, hck } `, template, target, igm, hck) } + +func resourceSplitter(resource string) string { + splits := strings.Split(resource, "/") + + return splits[len(splits)-1] +}