diff --git a/.changelog/3693.txt b/.changelog/3693.txt new file mode 100644 index 0000000000..e37a46dc72 --- /dev/null +++ b/.changelog/3693.txt @@ -0,0 +1,6 @@ +```release-note:enhancement +compute: Added `mode` to `google_compute_autoscaler` `autoscaling_policy` +``` +```release-note:enhancement +compute: Added `scale_down_control` for `google_compute_autoscaler` `autoscaling_policy` (beta only) +``` diff --git a/google-beta/resource_compute_autoscaler.go b/google-beta/resource_compute_autoscaler.go index ed77e58795..21a8d36c8e 100644 --- a/google-beta/resource_compute_autoscaler.go +++ b/google-beta/resource_compute_autoscaler.go @@ -226,6 +226,55 @@ Stackdriver Monitoring metric. Possible values: ["GAUGE", "DELTA_PER_SECOND", "D }, }, }, + "mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"OFF", "ONLY_UP", "ON", ""}, false), + Description: `Defines operating mode for this policy. Default value: "ON" Possible values: ["OFF", "ONLY_UP", "ON"]`, + Default: "ON", + }, + "scale_down_control": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Defines scale down controls to reduce the risk of response latency +and outages due to abrupt scale-in events`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_scaled_down_replicas": { + Type: schema.TypeList, + Optional: true, + Description: `A nested object resource`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "fixed": { + Type: schema.TypeInt, + Optional: true, + Description: `Specifies a fixed number of VM instances. This must be a positive +integer.`, + }, + "percent": { + Type: schema.TypeInt, + Optional: true, + Description: `Specifies a percentage of instances between 0 to 100%, inclusive. +For example, specify 80 for 80%.`, + }, + }, + }, + AtLeastOneOf: []string{}, + }, + "time_window_sec": { + Type: schema.TypeInt, + Optional: true, + Description: `How long back autoscaling should look when computing recommendations +to include directives regarding slower scale down, as described above.`, + }, + }, + }, + AtLeastOneOf: []string{}, + }, }, }, }, @@ -540,6 +589,10 @@ func flattenComputeAutoscalerAutoscalingPolicy(v interface{}, d *schema.Resource flattenComputeAutoscalerAutoscalingPolicyMaxReplicas(original["maxNumReplicas"], d, config) transformed["cooldown_period"] = flattenComputeAutoscalerAutoscalingPolicyCooldownPeriod(original["coolDownPeriodSec"], d, config) + transformed["mode"] = + flattenComputeAutoscalerAutoscalingPolicyMode(original["mode"], d, config) + transformed["scale_down_control"] = + flattenComputeAutoscalerAutoscalingPolicyScaleDownControl(original["scaleDownControl"], d, config) transformed["cpu_utilization"] = flattenComputeAutoscalerAutoscalingPolicyCpuUtilization(original["cpuUtilization"], d, config) transformed["metric"] = @@ -599,6 +652,91 @@ func flattenComputeAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}, d *s return v // let terraform core handle it otherwise } +func flattenComputeAutoscalerAutoscalingPolicyMode(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyScaleDownControl(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["max_scaled_down_replicas"] = + flattenComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicas(original["maxScaledDownReplicas"], d, config) + transformed["time_window_sec"] = + flattenComputeAutoscalerAutoscalingPolicyScaleDownControlTimeWindowSec(original["timeWindowSec"], d, config) + return []interface{}{transformed} +} +func flattenComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicas(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["fixed"] = + flattenComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasFixed(original["fixed"], d, config) + transformed["percent"] = + flattenComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasPercent(original["percent"], d, config) + return []interface{}{transformed} +} +func flattenComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasFixed(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasPercent(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenComputeAutoscalerAutoscalingPolicyScaleDownControlTimeWindowSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + func flattenComputeAutoscalerAutoscalingPolicyCpuUtilization(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return nil @@ -727,6 +865,20 @@ func expandComputeAutoscalerAutoscalingPolicy(v interface{}, d TerraformResource transformed["coolDownPeriodSec"] = transformedCooldownPeriod } + transformedMode, err := expandComputeAutoscalerAutoscalingPolicyMode(original["mode"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMode); val.IsValid() && !isEmptyValue(val) { + transformed["mode"] = transformedMode + } + + transformedScaleDownControl, err := expandComputeAutoscalerAutoscalingPolicyScaleDownControl(original["scale_down_control"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedScaleDownControl); val.IsValid() && !isEmptyValue(val) { + transformed["scaleDownControl"] = transformedScaleDownControl + } + transformedCpuUtilization, err := expandComputeAutoscalerAutoscalingPolicyCpuUtilization(original["cpu_utilization"], d, config) if err != nil { return nil, err @@ -763,6 +915,74 @@ func expandComputeAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}, d Ter return v, nil } +func expandComputeAutoscalerAutoscalingPolicyMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyScaleDownControl(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMaxScaledDownReplicas, err := expandComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicas(original["max_scaled_down_replicas"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMaxScaledDownReplicas); val.IsValid() && !isEmptyValue(val) { + transformed["maxScaledDownReplicas"] = transformedMaxScaledDownReplicas + } + + transformedTimeWindowSec, err := expandComputeAutoscalerAutoscalingPolicyScaleDownControlTimeWindowSec(original["time_window_sec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTimeWindowSec); val.IsValid() && !isEmptyValue(val) { + transformed["timeWindowSec"] = transformedTimeWindowSec + } + + return transformed, nil +} + +func expandComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicas(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedFixed, err := expandComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasFixed(original["fixed"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFixed); val.IsValid() && !isEmptyValue(val) { + transformed["fixed"] = transformedFixed + } + + transformedPercent, err := expandComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasPercent(original["percent"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPercent); val.IsValid() && !isEmptyValue(val) { + transformed["percent"] = transformedPercent + } + + return transformed, nil +} + +func expandComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasFixed(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyScaleDownControlMaxScaledDownReplicasPercent(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyScaleDownControlTimeWindowSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeAutoscalerAutoscalingPolicyCpuUtilization(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google-beta/resource_compute_autoscaler_test.go b/google-beta/resource_compute_autoscaler_test.go index 666565d2c3..8a6443e40e 100644 --- a/google-beta/resource_compute_autoscaler_test.go +++ b/google-beta/resource_compute_autoscaler_test.go @@ -65,6 +65,31 @@ func TestAccComputeAutoscaler_multicondition(t *testing.T) { }) } +func TestAccComputeAutoscaler_scaleDownControl(t *testing.T) { + t.Parallel() + + var it_name = fmt.Sprintf("autoscaler-test-%s", randString(t, 10)) + var tp_name = fmt.Sprintf("autoscaler-test-%s", randString(t, 10)) + var igm_name = fmt.Sprintf("autoscaler-test-%s", randString(t, 10)) + var autoscaler_name = fmt.Sprintf("autoscaler-test-%s", randString(t, 10)) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeAutoscalerDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAutoscaler_scaleDownControl(it_name, tp_name, igm_name, autoscaler_name), + }, + { + ResourceName: "google_compute_autoscaler.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccComputeAutoscaler_scaffolding(it_name, tp_name, igm_name string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { @@ -183,3 +208,28 @@ resource "google_compute_autoscaler" "foobar" { } `, autoscaler_name) } + +func testAccComputeAutoscaler_scaleDownControl(it_name, tp_name, igm_name, autoscaler_name string) string { + return testAccComputeAutoscaler_scaffolding(it_name, tp_name, igm_name) + fmt.Sprintf(` +resource "google_compute_autoscaler" "foobar" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + zone = "us-central1-a" + target = google_compute_instance_group_manager.foobar.self_link + autoscaling_policy { + max_replicas = 10 + min_replicas = 1 + cooldown_period = 60 + cpu_utilization { + target = 0.5 + } + scale_down_control { + max_scaled_down_replicas { + percent = 80 + } + time_window_sec = 300 + } + } +} +`, autoscaler_name) +} diff --git a/google-beta/resource_compute_node_group.go b/google-beta/resource_compute_node_group.go index 3d3359e9bc..70d46c39d6 100644 --- a/google-beta/resource_compute_node_group.go +++ b/google-beta/resource_compute_node_group.go @@ -82,8 +82,8 @@ to 100 and greater than or equal to min-nodes.`, Description: `The autoscaling mode. Set to one of the following: - OFF: Disables the autoscaler. - ON: Enables scaling in and scaling out. - - ONLY_SCALE_OUT: Enables only scaling out. - You must use this mode if your node groups are configured to + - ONLY_SCALE_OUT: Enables only scaling out. + You must use this mode if your node groups are configured to restart their hosted VMs on minimal servers. Possible values: ["OFF", "ON", "ONLY_SCALE_OUT"]`, }, "min_nodes": { @@ -91,7 +91,7 @@ to 100 and greater than or equal to min-nodes.`, Computed: true, Optional: true, ForceNew: true, - Description: `Minimum size of the node group. Must be less + Description: `Minimum size of the node group. Must be less than or equal to max-nodes. The default value is 0.`, }, }, diff --git a/website/docs/r/compute_autoscaler.html.markdown b/website/docs/r/compute_autoscaler.html.markdown index 17a2e9eb92..1bfd537f02 100644 --- a/website/docs/r/compute_autoscaler.html.markdown +++ b/website/docs/r/compute_autoscaler.html.markdown @@ -249,6 +249,21 @@ The `autoscaling_policy` block supports: instance may take to initialize. To do this, create an instance and time the startup process. +* `mode` - + (Optional) + Defines operating mode for this policy. + + Default value: `ON` + Possible values are: + * `OFF` + * `ONLY_UP` + * `ON` + +* `scale_down_control` - + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) + Defines scale down controls to reduce the risk of response latency + and outages due to abrupt scale-in events Structure is documented below. + * `cpu_utilization` - (Optional) Defines the CPU utilization policy that allows the autoscaler to @@ -264,6 +279,30 @@ The `autoscaling_policy` block supports: Configuration parameters of autoscaling based on a load balancer. Structure is documented below. +The `scale_down_control` block supports: + +* `max_scaled_down_replicas` - + (Optional) + A nested object resource Structure is documented below. + +* `time_window_sec` - + (Optional) + How long back autoscaling should look when computing recommendations + to include directives regarding slower scale down, as described above. + + +The `max_scaled_down_replicas` block supports: + +* `fixed` - + (Optional) + Specifies a fixed number of VM instances. This must be a positive + integer. + +* `percent` - + (Optional) + Specifies a percentage of instances between 0 to 100%, inclusive. + For example, specify 80 for 80%. + The `cpu_utilization` block supports: * `target` - diff --git a/website/docs/r/compute_node_group.html.markdown b/website/docs/r/compute_node_group.html.markdown index b962bfbb5c..50952f99c0 100644 --- a/website/docs/r/compute_node_group.html.markdown +++ b/website/docs/r/compute_node_group.html.markdown @@ -137,8 +137,8 @@ The `autoscaling_policy` block supports: The autoscaling mode. Set to one of the following: - OFF: Disables the autoscaler. - ON: Enables scaling in and scaling out. - - ONLY_SCALE_OUT: Enables only scaling out. - You must use this mode if your node groups are configured to + - ONLY_SCALE_OUT: Enables only scaling out. + You must use this mode if your node groups are configured to restart their hosted VMs on minimal servers. Possible values are: @@ -148,7 +148,7 @@ The `autoscaling_policy` block supports: * `min_nodes` - (Optional) - Minimum size of the node group. Must be less + Minimum size of the node group. Must be less than or equal to max-nodes. The default value is 0. * `max_nodes` - diff --git a/website/docs/r/compute_region_disk_resource_policy_attachment.html.markdown b/website/docs/r/compute_region_disk_resource_policy_attachment.html.markdown index 36f4b7e8e2..af0b99e36f 100644 --- a/website/docs/r/compute_region_disk_resource_policy_attachment.html.markdown +++ b/website/docs/r/compute_region_disk_resource_policy_attachment.html.markdown @@ -25,7 +25,7 @@ description: |- Adds existing resource policies to a disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation. -~> **Note:** This resource does not support zonal disks (`google_compute_disk`). For zonal disks, please refer to [`google_compute_disk_resource_policy_attachment`](https://www.terraform.io/docs/providers/google/r/compute_disk_resource_policy_attachment.html) +~> **Note:** This resource does not support zonal disks (`google_compute_disk`). For zonal disks, please refer to [`google_compute_disk_resource_policy_attachment`](https://www.terraform.io/docs/providers/google/r/compute_disk_resource_policy_attachment.html)