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

Add mode enum and scale down controls for Compute AutoScaler #2214

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
6 changes: 6 additions & 0 deletions .changelog/3693.txt
Original file line number Diff line number Diff line change
@@ -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)
```
220 changes: 220 additions & 0 deletions google-beta/resource_compute_autoscaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{},
},
},
},
},
Expand Down Expand Up @@ -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"] =
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
50 changes: 50 additions & 0 deletions google-beta/resource_compute_autoscaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down Expand Up @@ -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)
}
6 changes: 3 additions & 3 deletions google-beta/resource_compute_node_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,16 @@ 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": {
Type: schema.TypeInt,
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.`,
},
},
Expand Down
39 changes: 39 additions & 0 deletions website/docs/r/compute_autoscaler.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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` -
Expand Down
Loading