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

rIGM rolling update support #1260

Merged
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
4 changes: 4 additions & 0 deletions google/resource_compute_instance_group_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,8 @@ func expandUpdatePolicy(configured []interface{}) *computeBeta.InstanceGroupMana
} else {
updatePolicy.MaxSurge = &computeBeta.FixedOrPercent{
Fixed: int64(data["max_surge_fixed"].(int)),
// allow setting this value to 0
ForceSendFields: []string{"Fixed"},
}
}

Expand All @@ -880,6 +882,8 @@ func expandUpdatePolicy(configured []interface{}) *computeBeta.InstanceGroupMana
} else {
updatePolicy.MaxUnavailable = &computeBeta.FixedOrPercent{
Fixed: int64(data["max_unavailable_fixed"].(int)),
// allow setting this value to 0
ForceSendFields: []string{"Fixed"},
}
}

Expand Down
93 changes: 93 additions & 0 deletions google/resource_compute_region_instance_group_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var RegionInstanceGroupManagerBaseApiVersion = v1
var RegionInstanceGroupManagerVersionedFeatures = []Feature{
Feature{Version: v0beta, Item: "auto_healing_policies"},
Feature{Version: v0beta, Item: "distribution_policy_zones"},
Feature{Version: v0beta, Item: "rolling_update_policy"},
}

func resourceComputeRegionInstanceGroupManager() *schema.Resource {
Expand Down Expand Up @@ -107,6 +108,13 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
Computed: true,
},

"update_strategy": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "NONE",
ValidateFunc: validation.StringInSlice([]string{"NONE", "ROLLING_UPDATE"}, false),
},

"target_pools": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -162,6 +170,61 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
},

"rolling_update_policy": &schema.Schema{
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"minimal_action": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"RESTART", "REPLACE"}, false),
},

"type": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"OPPORTUNISTIC", "PROACTIVE"}, false),
},

"max_surge_fixed": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 0,
ConflictsWith: []string{"rolling_update_policy.0.max_surge_percent"},
},

"max_surge_percent": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ConflictsWith: []string{"rolling_update_policy.0.max_surge_fixed"},
ValidateFunc: validation.IntBetween(0, 100),
},

"max_unavailable_fixed": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 0,
ConflictsWith: []string{"rolling_update_policy.0.max_unavailable_percent"},
},

"max_unavailable_percent": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ConflictsWith: []string{"rolling_update_policy.0.max_unavailable_fixed"},
ValidateFunc: validation.IntBetween(0, 100),
},

"min_ready_sec": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(0, 3600),
},
},
},
},
},
}
}
Expand All @@ -175,6 +238,10 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met
return err
}

if _, ok := d.GetOk("rolling_update_policy"); d.Get("update_strategy") == "ROLLING_UPDATE" && !ok {
return fmt.Errorf("[rolling_update_policy] must be set when 'update_strategy' is set to 'ROLLING_UPDATE'")
}

manager := &computeBeta.InstanceGroupManager{
Name: d.Get("name").(string),
Description: d.Get("description").(string),
Expand Down Expand Up @@ -323,6 +390,10 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met

d.Partial(true)

if _, ok := d.GetOk("rolling_update_policy"); d.Get("update_strategy") == "ROLLING_UPDATE" && !ok {
return fmt.Errorf("[rolling_update_policy] must be set when 'update_strategy' is set to 'ROLLING_UPDATE'")
}

if d.HasChange("target_pools") {
targetPools := convertStringSet(d.Get("target_pools").(*schema.Set))

Expand Down Expand Up @@ -405,6 +476,28 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
return err
}

if d.Get("update_strategy").(string) == "ROLLING_UPDATE" {
// UpdatePolicy is set for InstanceGroupManager on update only, because it is only relevant for `Patch` calls.
// Other tools(gcloud and UI) capable of executing the same `ROLLING UPDATE` call
// expect those values to be provided by user as part of the call
// or provide their own defaults without respecting what was previously set on UpdateManager.
// To follow the same logic, we provide policy values on relevant update change only.
manager := &computeBeta.InstanceGroupManager{
UpdatePolicy: expandUpdatePolicy(d.Get("rolling_update_policy").([]interface{})),
}

op, err = config.clientComputeBeta.RegionInstanceGroupManagers.Patch(
project, region, d.Id(), manager).Do()
if err != nil {
return fmt.Errorf("Error updating managed group instances: %s", err)
}

err = computeSharedOperationWait(config.clientCompute, op, project, "Updating managed group instances")
if err != nil {
return err
}
}

d.SetPartial("instance_template")
}

Expand Down
217 changes: 217 additions & 0 deletions google/resource_compute_region_instance_group_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,85 @@ func TestAccRegionInstanceGroupManager_updateLifecycle(t *testing.T) {
})
}

func TestAccRegionInstanceGroupManager_updateStrategy(t *testing.T) {
t.Parallel()

var manager compute.InstanceGroupManager
igm := 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: testAccRegionInstanceGroupManager_updateStrategy(igm),
Check: resource.ComposeTestCheckFunc(
testAccCheckRegionInstanceGroupManagerExists(
"google_compute_region_instance_group_manager.igm-update-strategy", &manager),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-update-strategy", "update_strategy", "NONE"),
),
},
},
})
}

func TestAccRegionInstanceGroupManager_rollingUpdatePolicy(t *testing.T) {
t.Parallel()

var manager computeBeta.InstanceGroupManager

igm := 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: testAccRegionInstanceGroupManager_rollingUpdatePolicy(igm),
Check: resource.ComposeTestCheckFunc(
testAccCheckRegionInstanceGroupManagerBetaExists(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", &manager),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "update_strategy", "ROLLING_UPDATE"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.type", "PROACTIVE"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.minimal_action", "REPLACE"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.max_surge_fixed", "2"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.max_unavailable_fixed", "2"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.min_ready_sec", "20"),
),
},
resource.TestStep{
Config: testAccRegionInstanceGroupManager_rollingUpdatePolicy2(igm),
Check: resource.ComposeTestCheckFunc(
testAccCheckRegionInstanceGroupManagerBetaExists(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", &manager),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "update_strategy", "ROLLING_UPDATE"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.type", "PROACTIVE"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.minimal_action", "REPLACE"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.max_surge_fixed", "2"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.max_unavailable_fixed", "0"),
resource.TestCheckResourceAttr(
"google_compute_region_instance_group_manager.igm-rolling-update-policy", "rolling_update_policy.0.min_ready_sec", "10"),
testAccCheckInstanceGroupManagerRollingUpdatePolicy(
&manager, "google_compute_region_instance_group_manager.igm-rolling-update-policy"),
),
},
},
})
}
func TestAccRegionInstanceGroupManager_separateRegions(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -901,3 +980,141 @@ resource "google_compute_region_instance_group_manager" "igm-basic" {
}
`, template, igm, strings.Join(zones, "\",\""))
}

func testAccRegionInstanceGroupManager_updateStrategy(igm string) string {
return fmt.Sprintf(`
resource "google_compute_instance_template" "igm-update-strategy" {
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["terraform-testing"]

disk {
source_image = "debian-cloud/debian-8-jessie-v20160803"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}

lifecycle {
create_before_destroy = true
}
}

resource "google_compute_region_instance_group_manager" "igm-update-strategy" {
description = "Terraform test instance group manager"
name = "%s"
instance_template = "${google_compute_instance_template.igm-update-strategy.self_link}"
base_instance_name = "rigm-update-strategy"
region = "us-central1"
target_size = 2
update_strategy = "NONE"
named_port {
name = "customhttp"
port = 8080
}
}`, igm)
}

func testAccRegionInstanceGroupManager_rollingUpdatePolicy(igm string) string {
return fmt.Sprintf(`
resource "google_compute_instance_template" "igm-rolling-update-policy" {
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["terraform-testing"]

disk {
source_image = "debian-cloud/debian-8-jessie-v20160803"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}

lifecycle {
create_before_destroy = true
}
}

resource "google_compute_region_instance_group_manager" "igm-rolling-update-policy" {
description = "Terraform test instance group manager"
name = "%s"
instance_template = "${google_compute_instance_template.igm-rolling-update-policy.self_link}"
base_instance_name = "igm-rolling-update-policy"
region = "us-central1"
target_size = 4
distribution_policy_zones = ["us-central1-a", "us-central1-f"]
update_strategy = "ROLLING_UPDATE"

rolling_update_policy {
type = "PROACTIVE"
minimal_action = "REPLACE"
max_surge_fixed = 2
max_unavailable_fixed = 2
min_ready_sec = 20
}

named_port {
name = "customhttp"
port = 8080
}
}`, igm)
}

func testAccRegionInstanceGroupManager_rollingUpdatePolicy2(igm string) string {
return fmt.Sprintf(`
resource "google_compute_instance_template" "igm-rolling-update-policy" {
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["terraform-testing"]

disk {
source_image = "debian-cloud/debian-8-jessie-v20160803"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

lifecycle {
create_before_destroy = true
}
}

resource "google_compute_region_instance_group_manager" "igm-rolling-update-policy" {
description = "Terraform test instance group manager"
name = "%s"
instance_template = "${google_compute_instance_template.igm-rolling-update-policy.self_link}"
base_instance_name = "igm-rolling-update-policy"
region = "us-central1"
distribution_policy_zones = ["us-central1-a", "us-central1-f"]
target_size = 3
update_strategy = "ROLLING_UPDATE"

rolling_update_policy {
type = "PROACTIVE"
minimal_action = "REPLACE"
max_surge_fixed = 2
max_unavailable_fixed = 0
min_ready_sec = 10
}
named_port {
name = "customhttp"
port = 8080
}
}`, igm)
}
Loading