Start removing beta igm/rigm fields. (#2393)

<!-- This change is generated by MagicModules. -->
/cc @rileykarson
This commit is contained in:
The Magician 2018-11-20 15:35:04 -08:00 committed by Nathan McKinley
parent 1fe4aca6e7
commit f26c910f80
5 changed files with 113 additions and 1090 deletions

View File

@ -44,37 +44,42 @@ func resourceComputeInstanceGroupManager() *schema.Resource {
}, },
"version": &schema.Schema{ "version": &schema.Schema{
Deprecated: "This field is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.", Type: schema.TypeList,
Type: schema.TypeList, Optional: true,
Optional: true, Computed: true,
Computed: true, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "name": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
}, },
"instance_template": &schema.Schema{ "instance_template": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
DiffSuppressFunc: compareSelfLinkRelativePaths, DiffSuppressFunc: compareSelfLinkRelativePaths,
}, },
"target_size": &schema.Schema{ "target_size": &schema.Schema{
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
MaxItems: 1, MaxItems: 1,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"fixed": &schema.Schema{ "fixed": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
}, },
"percent": &schema.Schema{ "percent": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 100), ValidateFunc: validation.IntBetween(0, 100),
}, },
}, },
@ -114,7 +119,7 @@ func resourceComputeInstanceGroupManager() *schema.Resource {
}, },
"named_port": &schema.Schema{ "named_port": &schema.Schema{
Type: schema.TypeList, Type: schema.TypeSet,
Optional: true, Optional: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -175,21 +180,23 @@ func resourceComputeInstanceGroupManager() *schema.Resource {
}, },
"auto_healing_policies": &schema.Schema{ "auto_healing_policies": &schema.Schema{
Deprecated: "This field is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.", Type: schema.TypeList,
Type: schema.TypeList, Optional: true,
Optional: true, MaxItems: 1,
MaxItems: 1, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"health_check": &schema.Schema{ "health_check": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
DiffSuppressFunc: compareSelfLinkRelativePaths, DiffSuppressFunc: compareSelfLinkRelativePaths,
}, },
"initial_delay_sec": &schema.Schema{ "initial_delay_sec": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 3600), ValidateFunc: validation.IntBetween(0, 3600),
}, },
}, },
@ -197,54 +204,57 @@ func resourceComputeInstanceGroupManager() *schema.Resource {
}, },
"rolling_update_policy": &schema.Schema{ "rolling_update_policy": &schema.Schema{
Deprecated: "This field is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.", Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Type: schema.TypeList, Computed: true,
Optional: true, Type: schema.TypeList,
MaxItems: 1, Optional: true,
MaxItems: 1,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"minimal_action": &schema.Schema{ "minimal_action": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.StringInSlice([]string{"RESTART", "REPLACE"}, false), ValidateFunc: validation.StringInSlice([]string{"RESTART", "REPLACE"}, false),
}, },
"type": &schema.Schema{ "type": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.StringInSlice([]string{"OPPORTUNISTIC", "PROACTIVE"}, false), ValidateFunc: validation.StringInSlice([]string{"OPPORTUNISTIC", "PROACTIVE"}, false),
}, },
"max_surge_fixed": &schema.Schema{ "max_surge_fixed": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Default: 1, Computed: true,
ConflictsWith: []string{"rolling_update_policy.0.max_surge_percent"}, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
}, },
"max_surge_percent": &schema.Schema{ "max_surge_percent": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
ConflictsWith: []string{"rolling_update_policy.0.max_surge_fixed"}, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 100), ValidateFunc: validation.IntBetween(0, 100),
}, },
"max_unavailable_fixed": &schema.Schema{ "max_unavailable_fixed": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Default: 1, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ConflictsWith: []string{"rolling_update_policy.0.max_unavailable_percent"},
}, },
"max_unavailable_percent": &schema.Schema{ "max_unavailable_percent": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
ConflictsWith: []string{"rolling_update_policy.0.max_unavailable_fixed"}, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 100), ValidateFunc: validation.IntBetween(0, 100),
}, },
"min_ready_sec": &schema.Schema{ "min_ready_sec": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Optional: true, Optional: true,
ValidateFunc: validation.IntBetween(0, 3600), ValidateFunc: validation.IntBetween(0, 3600),
}, },
@ -300,21 +310,15 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte
return err 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'")
}
// Build the parameter // Build the parameter
manager := &computeBeta.InstanceGroupManager{ manager := &computeBeta.InstanceGroupManager{
Name: d.Get("name").(string), Name: d.Get("name").(string),
Description: d.Get("description").(string), Description: d.Get("description").(string),
BaseInstanceName: d.Get("base_instance_name").(string), BaseInstanceName: d.Get("base_instance_name").(string),
InstanceTemplate: d.Get("instance_template").(string), InstanceTemplate: d.Get("instance_template").(string),
TargetSize: int64(d.Get("target_size").(int)), TargetSize: int64(d.Get("target_size").(int)),
NamedPorts: getNamedPortsBeta(d.Get("named_port").([]interface{})), NamedPorts: getNamedPortsBeta(d.Get("named_port").(*schema.Set).List()),
TargetPools: convertStringSet(d.Get("target_pools").(*schema.Set)), TargetPools: convertStringSet(d.Get("target_pools").(*schema.Set)),
AutoHealingPolicies: expandAutoHealingPolicies(d.Get("auto_healing_policies").([]interface{})),
Versions: expandVersions(d.Get("version").([]interface{})),
// Force send TargetSize to allow a value of 0. // Force send TargetSize to allow a value of 0.
ForceSendFields: []string{"TargetSize"}, ForceSendFields: []string{"TargetSize"},
} }
@ -449,9 +453,6 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
d.Set("base_instance_name", manager.BaseInstanceName) d.Set("base_instance_name", manager.BaseInstanceName)
d.Set("instance_template", ConvertSelfLinkToV1(manager.InstanceTemplate)) d.Set("instance_template", ConvertSelfLinkToV1(manager.InstanceTemplate))
if err := d.Set("version", flattenVersions(manager.Versions)); err != nil {
return err
}
d.Set("name", manager.Name) d.Set("name", manager.Name)
d.Set("zone", GetResourceNameFromSelfLink(manager.Zone)) d.Set("zone", GetResourceNameFromSelfLink(manager.Zone))
d.Set("description", manager.Description) d.Set("description", manager.Description)
@ -472,9 +473,10 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
update_strategy = "REPLACE" update_strategy = "REPLACE"
} }
d.Set("update_strategy", update_strategy.(string)) d.Set("update_strategy", update_strategy.(string))
if err = d.Set("auto_healing_policies", flattenAutoHealingPolicies(manager.AutoHealingPolicies)); err != nil {
return fmt.Errorf("Error setting auto_healing_policies in state: %s", err.Error()) // When we make a list Removed, we see a permadiff from `field_name.#: "" => "<computed>"`. Set to nil in Read so we see no diff.
} d.Set("version", nil)
d.Set("rolling_update_policy", nil)
if d.Get("wait_for_instances").(bool) { if d.Get("wait_for_instances").(bool) {
conf := resource.StateChangeConf{ conf := resource.StateChangeConf{
@ -495,7 +497,7 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
// Updates an instance group manager by applying the update strategy (REPLACE, RESTART) // Updates an instance group manager by applying the update strategy (REPLACE, RESTART)
// and rolling update policy (PROACTIVE, OPPORTUNISTIC). Updates performed by API // and rolling update policy (PROACTIVE, OPPORTUNISTIC). Updates performed by API
// are OPPORTUNISTIC by default. // are OPPORTUNISTIC by default.
func performZoneUpdate(config *Config, id string, updateStrategy string, rollingUpdatePolicy *computeBeta.InstanceGroupManagerUpdatePolicy, versions []*computeBeta.InstanceGroupManagerVersion, project string, zone string) error { func performZoneUpdate(config *Config, id string, updateStrategy string, project string, zone string) error {
if updateStrategy == "RESTART" || updateStrategy == "REPLACE" { if updateStrategy == "RESTART" || updateStrategy == "REPLACE" {
managedInstances, err := config.clientComputeBeta.InstanceGroupManagers.ListManagedInstances(project, zone, id).Do() managedInstances, err := config.clientComputeBeta.InstanceGroupManagers.ListManagedInstances(project, zone, id).Do()
if err != nil { if err != nil {
@ -524,28 +526,6 @@ func performZoneUpdate(config *Config, id string, updateStrategy string, rolling
} }
} }
if updateStrategy == "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: rollingUpdatePolicy,
Versions: versions,
}
op, err := config.clientComputeBeta.InstanceGroupManagers.Patch(project, zone, 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
}
}
return nil return nil
} }
@ -571,10 +551,6 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
d.Partial(true) 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 target_pools changes then update // If target_pools changes then update
if d.HasChange("target_pools") { if d.HasChange("target_pools") {
targetPools := convertStringSet(d.Get("target_pools").(*schema.Set)) targetPools := convertStringSet(d.Get("target_pools").(*schema.Set))
@ -605,7 +581,7 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
if d.HasChange("named_port") { if d.HasChange("named_port") {
// Build the parameters for a "SetNamedPorts" request: // Build the parameters for a "SetNamedPorts" request:
namedPorts := getNamedPortsBeta(d.Get("named_port").([]interface{})) namedPorts := getNamedPortsBeta(d.Get("named_port").(*schema.Set).List())
setNamedPorts := &computeBeta.InstanceGroupsSetNamedPortsRequest{ setNamedPorts := &computeBeta.InstanceGroupsSetNamedPortsRequest{
NamedPorts: namedPorts, NamedPorts: namedPorts,
} }
@ -645,29 +621,6 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
d.SetPartial("target_size") 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(
zonalID.Project, zonalID.Zone, zonalID.Name, setAutoHealingPoliciesRequest).Do()
if err != nil {
return fmt.Errorf("Error updating AutoHealingPolicies: %s", err)
}
// Wait for the operation to complete
err = computeSharedOperationWait(config.clientCompute, op, zonalID.Project, "Updating AutoHealingPolicies")
if err != nil {
return err
}
d.SetPartial("auto_healing_policies")
}
// If instance_template changes then update // If instance_template changes then update
if d.HasChange("instance_template") { if d.HasChange("instance_template") {
// Build the parameter // Build the parameter
@ -688,24 +641,10 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
} }
updateStrategy := d.Get("update_strategy").(string) updateStrategy := d.Get("update_strategy").(string)
rollingUpdatePolicy := expandUpdatePolicy(d.Get("rolling_update_policy").([]interface{})) err = performZoneUpdate(config, zonalID.Name, updateStrategy, zonalID.Project, zonalID.Zone)
err = performZoneUpdate(config, zonalID.Name, updateStrategy, rollingUpdatePolicy, nil, zonalID.Project, zonalID.Zone)
d.SetPartial("instance_template") d.SetPartial("instance_template")
} }
// If version changes then update
if d.HasChange("version") {
updateStrategy := d.Get("update_strategy").(string)
rollingUpdatePolicy := expandUpdatePolicy(d.Get("rolling_update_policy").([]interface{}))
versions := expandVersions(d.Get("version").([]interface{}))
err = performZoneUpdate(config, zonalID.Name, updateStrategy, rollingUpdatePolicy, versions, zonalID.Project, zonalID.Zone)
if err != nil {
return err
}
d.SetPartial("version")
}
d.Partial(false) d.Partial(false)
return resourceComputeInstanceGroupManagerRead(d, meta) return resourceComputeInstanceGroupManagerRead(d, meta)
@ -776,106 +715,6 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte
return nil 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 expandVersions(configured []interface{}) []*computeBeta.InstanceGroupManagerVersion {
versions := make([]*computeBeta.InstanceGroupManagerVersion, 0, len(configured))
for _, raw := range configured {
data := raw.(map[string]interface{})
version := computeBeta.InstanceGroupManagerVersion{
Name: data["name"].(string),
InstanceTemplate: data["instance_template"].(string),
TargetSize: expandFixedOrPercent(data["target_size"].([]interface{})),
}
versions = append(versions, &version)
}
return versions
}
func expandFixedOrPercent(configured []interface{}) *computeBeta.FixedOrPercent {
fixedOrPercent := &computeBeta.FixedOrPercent{}
for _, raw := range configured {
data := raw.(map[string]interface{})
if percent := data["percent"]; percent.(int) > 0 {
fixedOrPercent.Percent = int64(percent.(int))
} else {
fixedOrPercent.Fixed = int64(data["fixed"].(int))
fixedOrPercent.ForceSendFields = []string{"Fixed"}
}
}
return fixedOrPercent
}
func expandUpdatePolicy(configured []interface{}) *computeBeta.InstanceGroupManagerUpdatePolicy {
updatePolicy := &computeBeta.InstanceGroupManagerUpdatePolicy{}
for _, raw := range configured {
data := raw.(map[string]interface{})
updatePolicy.MinimalAction = data["minimal_action"].(string)
updatePolicy.Type = data["type"].(string)
// percent and fixed values are conflicting
// when the percent values are set, the fixed values will be ignored
if v := data["max_surge_percent"]; v.(int) > 0 {
updatePolicy.MaxSurge = &computeBeta.FixedOrPercent{
Percent: int64(v.(int)),
}
} else {
updatePolicy.MaxSurge = &computeBeta.FixedOrPercent{
Fixed: int64(data["max_surge_fixed"].(int)),
// allow setting this value to 0
ForceSendFields: []string{"Fixed"},
}
}
if v := data["max_unavailable_percent"]; v.(int) > 0 {
updatePolicy.MaxUnavailable = &computeBeta.FixedOrPercent{
Percent: int64(v.(int)),
}
} else {
updatePolicy.MaxUnavailable = &computeBeta.FixedOrPercent{
Fixed: int64(data["max_unavailable_fixed"].(int)),
// allow setting this value to 0
ForceSendFields: []string{"Fixed"},
}
}
if v, ok := data["min_ready_sec"]; ok {
updatePolicy.MinReadySec = int64(v.(int))
}
}
return updatePolicy
}
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
}
func resourceInstanceGroupManagerStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { func resourceInstanceGroupManagerStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
d.Set("wait_for_instances", false) d.Set("wait_for_instances", false)
zonalID, err := parseInstanceGroupManagerId(d.Id()) zonalID, err := parseInstanceGroupManagerId(d.Id())

View File

@ -150,28 +150,6 @@ func TestAccInstanceGroupManager_updateStrategy(t *testing.T) {
}) })
} }
func TestAccInstanceGroupManager_rollingUpdatePolicy(t *testing.T) {
t.Parallel()
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{
{
Config: testAccInstanceGroupManager_rollingUpdatePolicy(igm),
},
// No import step because rolling updates are broken and the field will be removed in 2.0.0.
// TODO(danawillow): Remove this test once we've removed the field.
{
Config: testAccInstanceGroupManager_rollingUpdatePolicy2(igm),
},
},
})
}
func TestAccInstanceGroupManager_separateRegions(t *testing.T) { func TestAccInstanceGroupManager_separateRegions(t *testing.T) {
t.Parallel() t.Parallel()
@ -200,85 +178,6 @@ func TestAccInstanceGroupManager_separateRegions(t *testing.T) {
}) })
} }
func TestAccInstanceGroupManager_versions(t *testing.T) {
t.Parallel()
primaryTemplate := fmt.Sprintf("igm-test-%s", acctest.RandString(10))
canaryTemplate := fmt.Sprintf("igm-test-%s", acctest.RandString(10))
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{
{
Config: testAccInstanceGroupManager_versions(primaryTemplate, canaryTemplate, igm),
},
{
ResourceName: "google_compute_instance_group_manager.igm-basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccInstanceGroupManager_autoHealingPolicies(t *testing.T) {
t.Parallel()
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{
{
Config: testAccInstanceGroupManager_autoHealingPolicies(template, target, igm, hck),
},
{
ResourceName: "google_compute_instance_group_manager.igm-basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
// This test is to make sure that a single version resource can link to a versioned resource
// without perpetual diffs because the self links mismatch.
// Once auto_healing_policies is no longer beta, we will need to use a new field or resource
// with Beta fields.
func TestAccInstanceGroupManager_selfLinkStability(t *testing.T) {
t.Parallel()
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))
autoscaler := fmt.Sprintf("igm-test-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckInstanceGroupManagerDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceGroupManager_selfLinkStability(template, target, igm, hck, autoscaler),
},
{
ResourceName: "google_compute_instance_group_manager.igm-basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccCheckInstanceGroupManagerDestroy(s *terraform.State) error { func testAccCheckInstanceGroupManagerDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config) config := testAccProvider.Meta().(*Config)
@ -643,108 +542,6 @@ func testAccInstanceGroupManager_updateStrategy(igm string) string {
}`, igm) }`, igm)
} }
func testAccInstanceGroupManager_rollingUpdatePolicy(igm string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-rolling-update-policy" {
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["terraform-testing"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
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_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"
zone = "us-central1-c"
target_size = 3
update_strategy = "ROLLING_UPDATE"
rolling_update_policy {
type = "PROACTIVE"
minimal_action = "REPLACE"
max_surge_percent = 50
max_unavailable_percent = 50
min_ready_sec = 20
}
named_port {
name = "customhttp"
port = 8080
}
}`, igm)
}
func testAccInstanceGroupManager_rollingUpdatePolicy2(igm string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-rolling-update-policy" {
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["terraform-testing"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
auto_delete = true
boot = true
}
network_interface {
network = "default"
}
lifecycle {
create_before_destroy = true
}
}
resource "google_compute_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"
zone = "us-central1-c"
target_size = 3
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 testAccInstanceGroupManager_separateRegions(igm1, igm2 string) string { func testAccInstanceGroupManager_separateRegions(igm1, igm2 string) string {
return fmt.Sprintf(` return fmt.Sprintf(`
data "google_compute_image" "my_image" { data "google_compute_image" "my_image" {
@ -795,207 +592,3 @@ func testAccInstanceGroupManager_separateRegions(igm1, igm2 string) string {
} }
`, igm1, igm2) `, igm1, igm2)
} }
func testAccInstanceGroupManager_autoHealingPolicies(template, target, igm, hck string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-basic" {
name = "%s"
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["foo", "bar"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
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)
}
func testAccInstanceGroupManager_versions(primaryTemplate string, canaryTemplate string, igm string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-primary" {
name = "%s"
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["foo", "bar"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
auto_delete = true
boot = true
}
network_interface {
network = "default"
}
metadata {
foo = "bar"
}
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
resource "google_compute_instance_template" "igm-canary" {
name = "%s"
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["foo", "bar"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
auto_delete = true
boot = true
}
network_interface {
network = "default"
}
metadata {
foo = "bar"
}
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
resource "google_compute_instance_group_manager" "igm-basic" {
description = "Terraform test instance group manager"
name = "%s"
base_instance_name = "igm-basic"
zone = "us-central1-c"
target_size = 2
version {
name = "primary"
instance_template = "${google_compute_instance_template.igm-primary.self_link}"
}
version {
name = "canary"
instance_template = "${google_compute_instance_template.igm-canary.self_link}"
target_size {
fixed = 1
}
}
}
`, primaryTemplate, canaryTemplate, igm)
}
// This test is to make sure that a single version resource can link to a versioned resource
// without perpetual diffs because the self links mismatch.
// Once auto_healing_policies is no longer beta, we will need to use a new field or resource
// with Beta fields.
func testAccInstanceGroupManager_selfLinkStability(template, target, igm, hck, autoscaler string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-basic" {
name = "%s"
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["foo", "bar"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
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
}
resource "google_compute_autoscaler" "foobar" {
name = "%s"
zone = "us-central1-c"
target = "${google_compute_instance_group_manager.igm-basic.self_link}"
autoscaling_policy = {
max_replicas = 10
min_replicas = 1
cooldown_period = 60
cpu_utilization = {
target = 0.5
}
}
}
`, template, target, igm, hck, autoscaler)
}

View File

@ -49,37 +49,42 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
}, },
"version": &schema.Schema{ "version": &schema.Schema{
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
Computed: true, Computed: true,
Deprecated: "This field is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.", Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "name": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
}, },
"instance_template": &schema.Schema{ "instance_template": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
DiffSuppressFunc: compareSelfLinkRelativePaths, DiffSuppressFunc: compareSelfLinkRelativePaths,
}, },
"target_size": &schema.Schema{ "target_size": &schema.Schema{
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
MaxItems: 1, MaxItems: 1,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"fixed": &schema.Schema{ "fixed": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
}, },
"percent": &schema.Schema{ "percent": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 100), ValidateFunc: validation.IntBetween(0, 100),
}, },
}, },
@ -118,7 +123,7 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
}, },
"named_port": &schema.Schema{ "named_port": &schema.Schema{
Type: schema.TypeList, Type: schema.TypeSet,
Optional: true, Optional: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -149,8 +154,9 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
"update_strategy": &schema.Schema{ "update_strategy": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Deprecated: "This field is deprecated as it has no functionality anymore. It will be removed in 3.0.0.",
Optional: true, Optional: true,
Default: "NONE", Computed: true,
ValidateFunc: validation.StringInSlice([]string{"NONE", "ROLLING_UPDATE"}, false), ValidateFunc: validation.StringInSlice([]string{"NONE", "ROLLING_UPDATE"}, false),
}, },
@ -178,21 +184,23 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
}, },
"auto_healing_policies": &schema.Schema{ "auto_healing_policies": &schema.Schema{
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
MaxItems: 1, MaxItems: 1,
Deprecated: "This field is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.", Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"health_check": &schema.Schema{ "health_check": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
DiffSuppressFunc: compareSelfLinkRelativePaths, DiffSuppressFunc: compareSelfLinkRelativePaths,
}, },
"initial_delay_sec": &schema.Schema{ "initial_delay_sec": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 3600), ValidateFunc: validation.IntBetween(0, 3600),
}, },
}, },
@ -212,54 +220,57 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
}, },
"rolling_update_policy": &schema.Schema{ "rolling_update_policy": &schema.Schema{
Deprecated: "This field is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.", Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Type: schema.TypeList, Computed: true,
Optional: true, Type: schema.TypeList,
MaxItems: 1, Optional: true,
MaxItems: 1,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"minimal_action": &schema.Schema{ "minimal_action": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.StringInSlice([]string{"RESTART", "REPLACE"}, false), ValidateFunc: validation.StringInSlice([]string{"RESTART", "REPLACE"}, false),
}, },
"type": &schema.Schema{ "type": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.StringInSlice([]string{"OPPORTUNISTIC", "PROACTIVE"}, false), ValidateFunc: validation.StringInSlice([]string{"OPPORTUNISTIC", "PROACTIVE"}, false),
}, },
"max_surge_fixed": &schema.Schema{ "max_surge_fixed": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Default: 0, Computed: true,
ConflictsWith: []string{"rolling_update_policy.0.max_surge_percent"}, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
}, },
"max_surge_percent": &schema.Schema{ "max_surge_percent": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
ConflictsWith: []string{"rolling_update_policy.0.max_surge_fixed"}, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 100), ValidateFunc: validation.IntBetween(0, 100),
}, },
"max_unavailable_fixed": &schema.Schema{ "max_unavailable_fixed": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Default: 0, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ConflictsWith: []string{"rolling_update_policy.0.max_unavailable_percent"},
}, },
"max_unavailable_percent": &schema.Schema{ "max_unavailable_percent": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
ConflictsWith: []string{"rolling_update_policy.0.max_unavailable_fixed"}, Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
ValidateFunc: validation.IntBetween(0, 100), ValidateFunc: validation.IntBetween(0, 100),
}, },
"min_ready_sec": &schema.Schema{ "min_ready_sec": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.",
Optional: true, Optional: true,
ValidateFunc: validation.IntBetween(0, 3600), ValidateFunc: validation.IntBetween(0, 3600),
}, },
@ -283,21 +294,15 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met
return err 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{ manager := &computeBeta.InstanceGroupManager{
Name: d.Get("name").(string), Name: d.Get("name").(string),
Description: d.Get("description").(string), Description: d.Get("description").(string),
BaseInstanceName: d.Get("base_instance_name").(string), BaseInstanceName: d.Get("base_instance_name").(string),
InstanceTemplate: d.Get("instance_template").(string), InstanceTemplate: d.Get("instance_template").(string),
TargetSize: int64(d.Get("target_size").(int)), TargetSize: int64(d.Get("target_size").(int)),
NamedPorts: getNamedPortsBeta(d.Get("named_port").([]interface{})), NamedPorts: getNamedPortsBeta(d.Get("named_port").(*schema.Set).List()),
TargetPools: convertStringSet(d.Get("target_pools").(*schema.Set)), TargetPools: convertStringSet(d.Get("target_pools").(*schema.Set)),
AutoHealingPolicies: expandAutoHealingPolicies(d.Get("auto_healing_policies").([]interface{})), DistributionPolicy: expandDistributionPolicy(d.Get("distribution_policy_zones").(*schema.Set)),
Versions: expandVersions(d.Get("version").([]interface{})),
DistributionPolicy: expandDistributionPolicy(d.Get("distribution_policy_zones").(*schema.Set)),
// Force send TargetSize to allow size of 0. // Force send TargetSize to allow size of 0.
ForceSendFields: []string{"TargetSize"}, ForceSendFields: []string{"TargetSize"},
} }
@ -390,9 +395,7 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta
d.Set("base_instance_name", manager.BaseInstanceName) d.Set("base_instance_name", manager.BaseInstanceName)
d.Set("instance_template", ConvertSelfLinkToV1(manager.InstanceTemplate)) d.Set("instance_template", ConvertSelfLinkToV1(manager.InstanceTemplate))
if err := d.Set("version", flattenVersions(manager.Versions)); err != nil {
return err
}
d.Set("name", manager.Name) d.Set("name", manager.Name)
d.Set("region", GetResourceNameFromSelfLink(manager.Region)) d.Set("region", GetResourceNameFromSelfLink(manager.Region))
d.Set("description", manager.Description) d.Set("description", manager.Description)
@ -406,18 +409,13 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta
} }
d.Set("fingerprint", manager.Fingerprint) d.Set("fingerprint", manager.Fingerprint)
d.Set("instance_group", ConvertSelfLinkToV1(manager.InstanceGroup)) d.Set("instance_group", ConvertSelfLinkToV1(manager.InstanceGroup))
if err := d.Set("auto_healing_policies", flattenAutoHealingPolicies(manager.AutoHealingPolicies)); err != nil {
return fmt.Errorf("Error setting auto_healing_policies in state: %s", err.Error())
}
if err := d.Set("distribution_policy_zones", flattenDistributionPolicy(manager.DistributionPolicy)); err != nil { if err := d.Set("distribution_policy_zones", flattenDistributionPolicy(manager.DistributionPolicy)); err != nil {
return err return err
} }
d.Set("self_link", ConvertSelfLinkToV1(manager.SelfLink)) d.Set("self_link", ConvertSelfLinkToV1(manager.SelfLink))
update_strategy, ok := d.GetOk("update_strategy") // When we make a list Removed, we see a permadiff from `field_name.#: "" => "<computed>"`. Set to nil in Read so we see no diff.
if !ok { d.Set("version", nil)
update_strategy = "NONE" d.Set("rolling_update_policy", nil)
}
d.Set("update_strategy", update_strategy.(string))
if d.Get("wait_for_instances").(bool) { if d.Get("wait_for_instances").(bool) {
conf := resource.StateChangeConf{ conf := resource.StateChangeConf{
@ -435,63 +433,6 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta
return nil return nil
} }
// Updates an instance group manager by applying the update strategy (REPLACE, RESTART)
// and rolling update policy (PROACTIVE, OPPORTUNISTIC). Updates performed by API
// are OPPORTUNISTIC by default.
func performRegionUpdate(config *Config, id string, updateStrategy string, rollingUpdatePolicy *computeBeta.InstanceGroupManagerUpdatePolicy, versions []*computeBeta.InstanceGroupManagerVersion, project string, region string) error {
if updateStrategy == "RESTART" {
managedInstances, err := config.clientComputeBeta.RegionInstanceGroupManagers.ListManagedInstances(project, region, id).Do()
if err != nil {
return fmt.Errorf("Error getting region instance group managers instances: %s", err)
}
managedInstanceCount := len(managedInstances.ManagedInstances)
instances := make([]string, managedInstanceCount)
for i, v := range managedInstances.ManagedInstances {
instances[i] = v.Instance
}
recreateInstances := &computeBeta.RegionInstanceGroupManagersRecreateRequest{
Instances: instances,
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.RecreateInstances(project, region, id, recreateInstances).Do()
if err != nil {
return fmt.Errorf("Error restarting region instance group managers instances: %s", err)
}
// Wait for the operation to complete
err = computeSharedOperationWaitTime(config.clientCompute, op, project, managedInstanceCount*4, "Restarting RegionInstanceGroupManagers instances")
if err != nil {
return err
}
}
if updateStrategy == "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: rollingUpdatePolicy,
Versions: versions,
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Patch(project, region, id, manager).Do()
if err != nil {
return fmt.Errorf("Error updating region managed group instances: %s", err)
}
err = computeSharedOperationWait(config.clientCompute, op, project, "Updating region managed group instances")
if err != nil {
return err
}
}
return nil
}
func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error { func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
@ -507,10 +448,6 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
d.Partial(true) 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") { if d.HasChange("target_pools") {
targetPools := convertStringSet(d.Get("target_pools").(*schema.Set)) targetPools := convertStringSet(d.Get("target_pools").(*schema.Set))
@ -555,28 +492,12 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
return err return err
} }
updateStrategy := d.Get("update_strategy").(string)
rollingUpdatePolicy := expandUpdatePolicy(d.Get("rolling_update_policy").([]interface{}))
err = performRegionUpdate(config, d.Id(), updateStrategy, rollingUpdatePolicy, nil, project, region)
d.SetPartial("instance_template") d.SetPartial("instance_template")
} }
// If version changes then update
if d.HasChange("version") {
updateStrategy := d.Get("update_strategy").(string)
rollingUpdatePolicy := expandUpdatePolicy(d.Get("rolling_update_policy").([]interface{}))
versions := expandVersions(d.Get("version").([]interface{}))
err = performRegionUpdate(config, d.Get("name").(string), updateStrategy, rollingUpdatePolicy, versions, project, region)
if err != nil {
return err
}
d.SetPartial("version")
}
if d.HasChange("named_port") { if d.HasChange("named_port") {
// Build the parameters for a "SetNamedPorts" request: // Build the parameters for a "SetNamedPorts" request:
namedPorts := getNamedPortsBeta(d.Get("named_port").([]interface{})) namedPorts := getNamedPortsBeta(d.Get("named_port").(*schema.Set).List())
setNamedPorts := &computeBeta.RegionInstanceGroupsSetNamedPortsRequest{ setNamedPorts := &computeBeta.RegionInstanceGroupsSetNamedPortsRequest{
NamedPorts: namedPorts, NamedPorts: namedPorts,
} }
@ -616,28 +537,6 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
d.SetPartial("target_size") d.SetPartial("target_size")
} }
if d.HasChange("auto_healing_policies") {
setAutoHealingPoliciesRequest := &computeBeta.RegionInstanceGroupManagersSetAutoHealingRequest{}
if v, ok := d.GetOk("auto_healing_policies"); ok {
setAutoHealingPoliciesRequest.AutoHealingPolicies = expandAutoHealingPolicies(v.([]interface{}))
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.SetAutoHealingPolicies(
project, region, d.Get("name").(string), setAutoHealingPoliciesRequest).Do()
if err != nil {
return fmt.Errorf("Error updating AutoHealingPolicies: %s", err)
}
// Wait for the operation to complete
err = computeSharedOperationWait(config.clientCompute, op, project, "Updating AutoHealingPolicies")
if err != nil {
return err
}
d.SetPartial("auto_healing_policies")
}
d.Partial(false) d.Partial(false)
return resourceComputeRegionInstanceGroupManagerRead(d, meta) return resourceComputeRegionInstanceGroupManagerRead(d, meta)

View File

@ -143,35 +143,15 @@ func TestAccRegionInstanceGroupManager_updateStrategy(t *testing.T) {
Config: testAccRegionInstanceGroupManager_updateStrategy(igm), Config: testAccRegionInstanceGroupManager_updateStrategy(igm),
}, },
{ {
ResourceName: "google_compute_region_instance_group_manager.igm-update-strategy", ResourceName: "google_compute_region_instance_group_manager.igm-update-strategy",
ImportState: true, ImportState: true,
ImportStateVerify: true, ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"update_strategy"},
}, },
}, },
}) })
} }
func TestAccRegionInstanceGroupManager_rollingUpdatePolicy(t *testing.T) {
t.Parallel()
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{
{
Config: testAccRegionInstanceGroupManager_rollingUpdatePolicy(igm),
},
// No import step because rolling updates are broken and the field will be removed in 2.0.0.
// TODO(danawillow): Remove this test once we've removed the field.
{
Config: testAccRegionInstanceGroupManager_rollingUpdatePolicy2(igm),
},
},
})
}
func TestAccRegionInstanceGroupManager_separateRegions(t *testing.T) { func TestAccRegionInstanceGroupManager_separateRegions(t *testing.T) {
t.Parallel() t.Parallel()
@ -200,55 +180,6 @@ func TestAccRegionInstanceGroupManager_separateRegions(t *testing.T) {
}) })
} }
func TestAccRegionInstanceGroupManager_versions(t *testing.T) {
t.Parallel()
primaryTemplate := fmt.Sprintf("igm-test-%s", acctest.RandString(10))
canaryTemplate := fmt.Sprintf("igm-test-%s", acctest.RandString(10))
igm := fmt.Sprintf("igm-test-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckRegionInstanceGroupManagerDestroy,
Steps: []resource.TestStep{
{
Config: testAccRegionInstanceGroupManager_versions(primaryTemplate, canaryTemplate, igm),
},
{
ResourceName: "google_compute_region_instance_group_manager.igm-basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccRegionInstanceGroupManager_autoHealingPolicies(t *testing.T) {
t.Parallel()
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: testAccCheckRegionInstanceGroupManagerDestroy,
Steps: []resource.TestStep{
{
Config: testAccRegionInstanceGroupManager_autoHealingPolicies(template, target, igm, hck),
},
{
ResourceName: "google_compute_region_instance_group_manager.igm-basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccRegionInstanceGroupManager_distributionPolicy(t *testing.T) { func TestAccRegionInstanceGroupManager_distributionPolicy(t *testing.T) {
t.Parallel() t.Parallel()
@ -642,135 +573,6 @@ func testAccRegionInstanceGroupManager_separateRegions(igm1, igm2 string) string
`, igm1, igm2) `, igm1, igm2)
} }
func testAccRegionInstanceGroupManager_autoHealingPolicies(template, target, igm, hck string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-basic" {
name = "%s"
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["foo", "bar"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
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_region_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"
region = "us-central1"
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)
}
func testAccRegionInstanceGroupManager_versions(primaryTemplate string, canaryTemplate string, igm string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-primary" {
name = "%s"
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["foo", "bar"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
auto_delete = true
boot = true
}
network_interface {
network = "default"
}
metadata {
foo = "bar"
}
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
resource "google_compute_instance_template" "igm-canary" {
name = "%s"
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["foo", "bar"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
auto_delete = true
boot = true
}
network_interface {
network = "default"
}
metadata {
foo = "bar"
}
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
resource "google_compute_region_instance_group_manager" "igm-basic" {
description = "Terraform test region instance group manager"
name = "%s"
base_instance_name = "igm-basic"
region = "us-central1"
target_size = 2
version {
name = "primary"
instance_template = "${google_compute_instance_template.igm-primary.self_link}"
}
version {
name = "canary"
instance_template = "${google_compute_instance_template.igm-canary.self_link}"
target_size {
fixed = 1
}
}
}
`, primaryTemplate, canaryTemplate, igm)
}
func testAccRegionInstanceGroupManager_distributionPolicy(template, igm string, zones []string) string { func testAccRegionInstanceGroupManager_distributionPolicy(template, igm string, zones []string) string {
return fmt.Sprintf(` return fmt.Sprintf(`
data "google_compute_image" "my_image" { data "google_compute_image" "my_image" {
@ -853,110 +655,3 @@ resource "google_compute_region_instance_group_manager" "igm-update-strategy" {
} }
}`, igm) }`, igm)
} }
func testAccRegionInstanceGroupManager_rollingUpdatePolicy(igm string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-rolling-update-policy" {
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["terraform-testing"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
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(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance_template" "igm-rolling-update-policy" {
machine_type = "n1-standard-1"
can_ip_forward = false
tags = ["terraform-testing"]
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
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)
}

View File

@ -116,11 +116,8 @@ The following arguments are supported:
* `project` - (Optional) The ID of the project in which the resource belongs. If it * `project` - (Optional) The ID of the project in which the resource belongs. If it
is not provided, the provider project is used. is not provided, the provider project is used.
* `update_strategy` - (Optional, Default `"REPLACE"`) If the `instance_template` * `update_strategy` - (Optional, Default `"NONE"`) This field is deprecated as it has no functionality anymore.
resource is modified, a value of `"NONE"` will prevent any of the managed It previously turned update behaviour on and off. This field is only present in the `google` provider.
instances from being restarted by Terraform. A value of `"REPLACE"` will
restart all of the instances at once. This field is only present in the
`google` provider.
* `target_size` - (Optional) The target number of running instances for this managed * `target_size` - (Optional) The target number of running instances for this managed
instance group. This value should always be explicitly set unless this resource is attached to instance group. This value should always be explicitly set unless this resource is attached to