From 5976152ad975bbdfc7850ee4832b6609fd98cd57 Mon Sep 17 00:00:00 2001 From: The Magician Date: Wed, 27 Jun 2018 12:49:34 -0700 Subject: [PATCH] Add generated google_compute_autoscaler and google_compute_region_autoscaler resources. Because this adds the ability to import by more than just the name, we can get rid of all the code in resource_compute_autoscaler.go that tries to find the autoscaler in the provider-specified region. (#1700) --- google/provider_compute_gen.go | 2 + google/resource_compute_autoscaler.go | 829 ++++++++++++------ google/resource_compute_autoscaler_test.go | 21 +- google/resource_compute_region_autoscaler.go | 627 +++++++++++-- ...resource_compute_region_autoscaler_test.go | 18 +- .../docs/r/compute_autoscaler.html.markdown | 219 +++-- .../r/compute_region_autoscaler.html.markdown | 219 +++-- 7 files changed, 1458 insertions(+), 477 deletions(-) diff --git a/google/provider_compute_gen.go b/google/provider_compute_gen.go index 80f973d7..ba3db1e1 100644 --- a/google/provider_compute_gen.go +++ b/google/provider_compute_gen.go @@ -18,12 +18,14 @@ import "github.com/hashicorp/terraform/helper/schema" var GeneratedComputeResourcesMap = map[string]*schema.Resource{ "google_compute_address": resourceComputeAddress(), + "google_compute_autoscaler": resourceComputeAutoscaler(), "google_compute_backend_bucket": resourceComputeBackendBucket(), "google_compute_disk": resourceComputeDisk(), "google_compute_forwarding_rule": resourceComputeForwardingRule(), "google_compute_global_address": resourceComputeGlobalAddress(), "google_compute_http_health_check": resourceComputeHttpHealthCheck(), "google_compute_https_health_check": resourceComputeHttpsHealthCheck(), + "google_compute_region_autoscaler": resourceComputeRegionAutoscaler(), "google_compute_route": resourceComputeRoute(), "google_compute_ssl_policy": resourceComputeSslPolicy(), "google_compute_subnetwork": resourceComputeSubnetwork(), diff --git a/google/resource_compute_autoscaler.go b/google/resource_compute_autoscaler.go index 7bee4d91..fad2ba7d 100644 --- a/google/resource_compute_autoscaler.go +++ b/google/resource_compute_autoscaler.go @@ -1,133 +1,152 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + package google import ( "fmt" "log" - - "google.golang.org/api/compute/v1" + "reflect" + "strconv" + "time" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + compute "google.golang.org/api/compute/v1" ) -var autoscalingPolicy *schema.Schema = &schema.Schema{ - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "min_replicas": &schema.Schema{ - Type: schema.TypeInt, - Required: true, - }, - - "max_replicas": &schema.Schema{ - Type: schema.TypeInt, - Required: true, - }, - - "cooldown_period": &schema.Schema{ - Type: schema.TypeInt, - Optional: true, - Default: 60, - }, - - "cpu_utilization": &schema.Schema{ - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "target": &schema.Schema{ - Type: schema.TypeFloat, - Required: true, - }, - }, - }, - }, - - "metric": &schema.Schema{ - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ - Type: schema.TypeString, - Required: true, - }, - "target": &schema.Schema{ - Type: schema.TypeFloat, - Required: true, - }, - - "type": &schema.Schema{ - Type: schema.TypeString, - Required: true, - }, - }, - }, - }, - - "load_balancing_utilization": &schema.Schema{ - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "target": &schema.Schema{ - Type: schema.TypeFloat, - Required: true, - }, - }, - }, - }, - }, - }, -} - func resourceComputeAutoscaler() *schema.Resource { return &schema.Resource{ Create: resourceComputeAutoscalerCreate, Read: resourceComputeAutoscalerRead, Update: resourceComputeAutoscalerUpdate, Delete: resourceComputeAutoscalerDelete, + Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: resourceComputeAutoscalerImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(240 * time.Second), + Update: schema.DefaultTimeout(240 * time.Second), + Delete: schema.DefaultTimeout(240 * time.Second), }, Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ - Type: schema.TypeString, - ForceNew: true, + "autoscaling_policy": { + Type: schema.TypeList, Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_replicas": { + Type: schema.TypeInt, + Required: true, + }, + "min_replicas": { + Type: schema.TypeInt, + Required: true, + }, + "cooldown_period": { + Type: schema.TypeInt, + Optional: true, + Default: 60, + }, + "cpu_utilization": { + Type: schema.TypeList, + Computed: true, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + "metric": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "target": { + Type: schema.TypeFloat, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"GAUGE", "DELTA_PER_SECOND", "DELTA_PER_MINUTE"}, false), + }, + }, + }, + }, + "load_balancing_utilization": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + }, + }, }, - - "target": &schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateGCPName, + }, + "target": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, + "description": { Type: schema.TypeString, - Required: true, + Optional: true, }, - - "zone": &schema.Schema{ + "zone": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, + "creation_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "project": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, - - "autoscaling_policy": autoscalingPolicy, - - "description": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - }, - - "project": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - }, - - "self_link": &schema.Schema{ + "self_link": { Type: schema.TypeString, Computed: true, }, @@ -135,64 +154,6 @@ func resourceComputeAutoscaler() *schema.Resource { } } -func buildAutoscaler(d *schema.ResourceData) (*compute.Autoscaler, error) { - // Build the parameter - scaler := &compute.Autoscaler{ - Name: d.Get("name").(string), - Target: d.Get("target").(string), - } - - // Optional fields - if v, ok := d.GetOk("description"); ok { - scaler.Description = v.(string) - } - - // You can only have 0 or 1 autoscaling policy per autoscaler, but HCL can't easily express - // "optional object", so instead we have "list of maximum size 1". - prefix := "autoscaling_policy.0." - - scaler.AutoscalingPolicy = &compute.AutoscalingPolicy{ - MaxNumReplicas: int64(d.Get(prefix + "max_replicas").(int)), - MinNumReplicas: int64(d.Get(prefix + "min_replicas").(int)), - CoolDownPeriodSec: int64(d.Get(prefix + "cooldown_period").(int)), - } - - // This list is MaxItems = 1 as well - you can only have 0 or 1 cpu utilization target per autoscaler. - if _, ok := d.GetOk(prefix + "cpu_utilization"); ok { - if d.Get(prefix+"cpu_utilization.0.target").(float64) != 0 { - scaler.AutoscalingPolicy.CpuUtilization = &compute.AutoscalingPolicyCpuUtilization{ - UtilizationTarget: d.Get(prefix + "cpu_utilization.0.target").(float64), - } - } - } - var customMetrics []*compute.AutoscalingPolicyCustomMetricUtilization - if metricCount, ok := d.GetOk(prefix + "metric.#"); ok { - for m := 0; m < metricCount.(int); m++ { - if d.Get(fmt.Sprintf("%smetric.%d.name", prefix, m)) != "" { - customMetrics = append(customMetrics, &compute.AutoscalingPolicyCustomMetricUtilization{ - Metric: d.Get(fmt.Sprintf("%smetric.%d.name", prefix, m)).(string), - UtilizationTarget: d.Get(fmt.Sprintf("%smetric.%d.target", prefix, m)).(float64), - UtilizationTargetType: d.Get(fmt.Sprintf("%smetric.%d.type", prefix, m)).(string), - }) - } - } - } - scaler.AutoscalingPolicy.CustomMetricUtilizations = customMetrics - if _, ok := d.GetOk("autoscaling_policy.0.load_balancing_utilization"); ok { - if d.Get(prefix+"load_balancing_utilization.0.target").(float64) != 0 { - lbuCount := d.Get(prefix + "load_balancing_utilization.#").(int) - if lbuCount != 1 { - return nil, fmt.Errorf("The autoscaling_policy must have exactly one load_balancing_utilization, found %d.", lbuCount) - } - scaler.AutoscalingPolicy.LoadBalancingUtilization = &compute.AutoscalingPolicyLoadBalancingUtilization{ - UtilizationTarget: d.Get(prefix + "load_balancing_utilization.0.target").(float64), - } - } - } - - return scaler, nil -} - func resourceComputeAutoscalerCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -201,74 +162,75 @@ func resourceComputeAutoscalerCreate(d *schema.ResourceData, meta interface{}) e return err } - // Get the zone - z, err := getZone(d, config) + obj := make(map[string]interface{}) + nameProp, err := expandComputeAutoscalerName(d.Get("name"), d, config) if err != nil { return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp } - log.Printf("[DEBUG] Loading zone: %s", z) - zone, err := config.clientCompute.Zones.Get( - project, z).Do() + descriptionProp, err := expandComputeAutoscalerDescription(d.Get("description"), d, config) if err != nil { - return fmt.Errorf( - "Error loading zone '%s': %s", z, err) + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + autoscalingPolicyProp, err := expandComputeAutoscalerAutoscalingPolicy(d.Get("autoscaling_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("autoscaling_policy"); !isEmptyValue(reflect.ValueOf(autoscalingPolicyProp)) && (ok || !reflect.DeepEqual(v, autoscalingPolicyProp)) { + obj["autoscalingPolicy"] = autoscalingPolicyProp + } + targetProp, err := expandComputeAutoscalerTarget(d.Get("target"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(targetProp)) && (ok || !reflect.DeepEqual(v, targetProp)) { + obj["target"] = targetProp + } + zoneProp, err := expandComputeAutoscalerZone(d.Get("zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("zone"); !isEmptyValue(reflect.ValueOf(zoneProp)) && (ok || !reflect.DeepEqual(v, zoneProp)) { + obj["zone"] = zoneProp } - scaler, err := buildAutoscaler(d) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/zones/{{zone}}/autoscalers") if err != nil { return err } - op, err := config.clientCompute.Autoscalers.Insert( - project, zone.Name, scaler).Do() + log.Printf("[DEBUG] Creating new Autoscaler: %#v", obj) + res, err := Post(config, url, obj) if err != nil { return fmt.Errorf("Error creating Autoscaler: %s", err) } - // It probably maybe worked, so store the ID now - d.SetId(scaler.Name) + // Store the ID now + id, err := replaceVars(d, config, "{{zone}}/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) - err = computeOperationWait(config.clientCompute, op, project, "Creating Autoscaler") + op := &compute.Operation{} + err = Convert(res, op) if err != nil { return err } - return resourceComputeAutoscalerRead(d, meta) -} + waitErr := computeOperationWaitTime( + config.clientCompute, op, project, "Creating Autoscaler", + int(d.Timeout(schema.TimeoutCreate).Minutes())) -func flattenAutoscalingPolicy(policy *compute.AutoscalingPolicy) []map[string]interface{} { - result := make([]map[string]interface{}, 0, 1) - policyMap := make(map[string]interface{}) - policyMap["max_replicas"] = policy.MaxNumReplicas - policyMap["min_replicas"] = policy.MinNumReplicas - policyMap["cooldown_period"] = policy.CoolDownPeriodSec - if policy.CpuUtilization != nil { - cpuUtils := make([]map[string]interface{}, 0, 1) - cpuUtil := make(map[string]interface{}) - cpuUtil["target"] = policy.CpuUtilization.UtilizationTarget - cpuUtils = append(cpuUtils, cpuUtil) - policyMap["cpu_utilization"] = cpuUtils + if waitErr != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create Autoscaler: %s", waitErr) } - if policy.LoadBalancingUtilization != nil { - loadBalancingUtils := make([]map[string]interface{}, 0, 1) - loadBalancingUtil := make(map[string]interface{}) - loadBalancingUtil["target"] = policy.LoadBalancingUtilization.UtilizationTarget - loadBalancingUtils = append(loadBalancingUtils, loadBalancingUtil) - policyMap["load_balancing_utilization"] = loadBalancingUtils - } - if policy.CustomMetricUtilizations != nil { - metricUtils := make([]map[string]interface{}, 0, len(policy.CustomMetricUtilizations)) - for _, customMetricUtilization := range policy.CustomMetricUtilizations { - metricUtil := make(map[string]interface{}) - metricUtil["target"] = customMetricUtilization.UtilizationTarget - metricUtil["name"] = customMetricUtilization.Metric - metricUtil["type"] = customMetricUtilization.UtilizationTargetType - metricUtils = append(metricUtils, metricUtil) - } - policyMap["metric"] = metricUtils - } - result = append(result, policyMap) - return result + + log.Printf("[DEBUG] Finished creating Autoscaler %q: %#v", d.Id(), res) + + return resourceComputeAutoscalerRead(d, meta) } func resourceComputeAutoscalerRead(d *schema.ResourceData, meta interface{}) error { @@ -279,49 +241,39 @@ func resourceComputeAutoscalerRead(d *schema.ResourceData, meta interface{}) err return err } - region, err := getRegion(d, config) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/zones/{{zone}}/autoscalers/{{name}}") if err != nil { return err } - var getAutoscaler = func(zone string) (interface{}, error) { - return config.clientCompute.Autoscalers.Get(project, zone, d.Id()).Do() + res, err := Get(config, url) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("ComputeAutoscaler %q", d.Id())) } - var scaler *compute.Autoscaler - var e error - if zone, _ := getZone(d, config); zone != "" { - scaler, e = config.clientCompute.Autoscalers.Get(project, zone, d.Id()).Do() - if e != nil { - return handleNotFoundError(e, d, fmt.Sprintf("Autoscaler %q", d.Id())) - } - } else { - // If the resource was imported, the only info we have is the ID. Try to find the resource - // by searching in the region of the project. - var resource interface{} - resource, e = getZonalResourceFromRegion(getAutoscaler, region, config.clientCompute, project) - - if e != nil { - return e - } - - scaler = resource.(*compute.Autoscaler) + if err := d.Set("creation_timestamp", flattenComputeAutoscalerCreationTimestamp(res["creationTimestamp"])); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) } - - if scaler == nil { - log.Printf("[WARN] Removing Autoscaler %q because it's gone", d.Get("name").(string)) - d.SetId("") - return nil + if err := d.Set("name", flattenComputeAutoscalerName(res["name"])); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) } - - d.Set("project", project) - d.Set("self_link", scaler.SelfLink) - d.Set("name", scaler.Name) - d.Set("target", scaler.Target) - d.Set("zone", GetResourceNameFromSelfLink(scaler.Zone)) - d.Set("description", scaler.Description) - if scaler.AutoscalingPolicy != nil { - d.Set("autoscaling_policy", flattenAutoscalingPolicy(scaler.AutoscalingPolicy)) + if err := d.Set("description", flattenComputeAutoscalerDescription(res["description"])); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) + } + if err := d.Set("autoscaling_policy", flattenComputeAutoscalerAutoscalingPolicy(res["autoscalingPolicy"])); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) + } + if err := d.Set("target", flattenComputeAutoscalerTarget(res["target"])); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) + } + if err := d.Set("zone", flattenComputeAutoscalerZone(res["zone"])); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) + } + if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading Autoscaler: %s", err) } return nil @@ -335,26 +287,60 @@ func resourceComputeAutoscalerUpdate(d *schema.ResourceData, meta interface{}) e return err } - zone, err := getZone(d, config) + obj := make(map[string]interface{}) + nameProp, err := expandComputeAutoscalerName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + descriptionProp, err := expandComputeAutoscalerDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + autoscalingPolicyProp, err := expandComputeAutoscalerAutoscalingPolicy(d.Get("autoscaling_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("autoscaling_policy"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, autoscalingPolicyProp)) { + obj["autoscalingPolicy"] = autoscalingPolicyProp + } + targetProp, err := expandComputeAutoscalerTarget(d.Get("target"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, targetProp)) { + obj["target"] = targetProp + } + zoneProp, err := expandComputeAutoscalerZone(d.Get("zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("zone"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, zoneProp)) { + obj["zone"] = zoneProp + } + + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/zones/{{zone}}/autoscalers?autoscaler={{name}}") if err != nil { return err } - scaler, err := buildAutoscaler(d) + log.Printf("[DEBUG] Updating Autoscaler %q: %#v", d.Id(), obj) + res, err := sendRequest(config, "PUT", url, obj) + + if err != nil { + return fmt.Errorf("Error updating Autoscaler %q: %s", d.Id(), err) + } + + op := &compute.Operation{} + err = Convert(res, op) if err != nil { return err } - op, err := config.clientCompute.Autoscalers.Update( - project, zone, scaler).Do() - if err != nil { - return fmt.Errorf("Error updating Autoscaler: %s", err) - } + err = computeOperationWaitTime( + config.clientCompute, op, project, "Updating Autoscaler", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) - // It probably maybe worked, so store the ID now - d.SetId(scaler.Name) - - err = computeOperationWait(config.clientCompute, op, project, "Updating Autoscaler") if err != nil { return err } @@ -370,21 +356,334 @@ func resourceComputeAutoscalerDelete(d *schema.ResourceData, meta interface{}) e return err } - zone, err := getZone(d, config) - if err != nil { - return err - } - op, err := config.clientCompute.Autoscalers.Delete( - project, zone, d.Id()).Do() - if err != nil { - return fmt.Errorf("Error deleting autoscaler: %s", err) - } - - err = computeOperationWait(config.clientCompute, op, project, "Deleting Autoscaler") + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/zones/{{zone}}/autoscalers/{{name}}") if err != nil { return err } - d.SetId("") + log.Printf("[DEBUG] Deleting Autoscaler %q", d.Id()) + res, err := Delete(config, url) + if err != nil { + return handleNotFoundError(err, d, "Autoscaler") + } + + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = computeOperationWaitTime( + config.clientCompute, op, project, "Deleting Autoscaler", + int(d.Timeout(schema.TimeoutDelete).Minutes())) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting Autoscaler %q: %#v", d.Id(), res) return nil } + +func resourceComputeAutoscalerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + parseImportId([]string{"projects/(?P[^/]+)/zones/(?P[^/]+)/autoscalers/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config) + + // Replace import id for the resource id + id, err := replaceVars(d, config, "{{zone}}/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenComputeAutoscalerCreationTimestamp(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerName(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerDescription(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerAutoscalingPolicy(v interface{}) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["min_replicas"] = + flattenComputeAutoscalerAutoscalingPolicyMinReplicas(original["minNumReplicas"]) + transformed["max_replicas"] = + flattenComputeAutoscalerAutoscalingPolicyMaxReplicas(original["maxNumReplicas"]) + transformed["cooldown_period"] = + flattenComputeAutoscalerAutoscalingPolicyCooldownPeriod(original["coolDownPeriodSec"]) + transformed["cpu_utilization"] = + flattenComputeAutoscalerAutoscalingPolicyCpuUtilization(original["cpuUtilization"]) + transformed["metric"] = + flattenComputeAutoscalerAutoscalingPolicyMetric(original["customMetricUtilizations"]) + transformed["load_balancing_utilization"] = + flattenComputeAutoscalerAutoscalingPolicyLoadBalancingUtilization(original["loadBalancingUtilization"]) + return []interface{}{transformed} +} +func flattenComputeAutoscalerAutoscalingPolicyMinReplicas(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyMaxReplicas(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyCpuUtilization(v interface{}) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["target"] = + flattenComputeAutoscalerAutoscalingPolicyCpuUtilizationTarget(original["utilizationTarget"]) + return []interface{}{transformed} +} +func flattenComputeAutoscalerAutoscalingPolicyCpuUtilizationTarget(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyMetric(v interface{}) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed = append(transformed, map[string]interface{}{ + "name": flattenComputeAutoscalerAutoscalingPolicyMetricName(original["metric"]), + "target": flattenComputeAutoscalerAutoscalingPolicyMetricTarget(original["utilizationTarget"]), + "type": flattenComputeAutoscalerAutoscalingPolicyMetricType(original["utilizationTargetType"]), + }) + } + return transformed +} +func flattenComputeAutoscalerAutoscalingPolicyMetricName(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyMetricTarget(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyMetricType(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerAutoscalingPolicyLoadBalancingUtilization(v interface{}) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["target"] = + flattenComputeAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(original["utilizationTarget"]) + return []interface{}{transformed} +} +func flattenComputeAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerTarget(v interface{}) interface{} { + return v +} + +func flattenComputeAutoscalerZone(v interface{}) interface{} { + return v +} + +func expandComputeAutoscalerName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicy(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMinReplicas, err := expandComputeAutoscalerAutoscalingPolicyMinReplicas(original["min_replicas"], d, config) + if err != nil { + return nil, err + } + transformed["minNumReplicas"] = transformedMinReplicas + transformedMaxReplicas, err := expandComputeAutoscalerAutoscalingPolicyMaxReplicas(original["max_replicas"], d, config) + if err != nil { + return nil, err + } + transformed["maxNumReplicas"] = transformedMaxReplicas + transformedCooldownPeriod, err := expandComputeAutoscalerAutoscalingPolicyCooldownPeriod(original["cooldown_period"], d, config) + if err != nil { + return nil, err + } + transformed["coolDownPeriodSec"] = transformedCooldownPeriod + transformedCpuUtilization, err := expandComputeAutoscalerAutoscalingPolicyCpuUtilization(original["cpu_utilization"], d, config) + if err != nil { + return nil, err + } + transformed["cpuUtilization"] = transformedCpuUtilization + transformedMetric, err := expandComputeAutoscalerAutoscalingPolicyMetric(original["metric"], d, config) + if err != nil { + return nil, err + } + transformed["customMetricUtilizations"] = transformedMetric + transformedLoadBalancingUtilization, err := expandComputeAutoscalerAutoscalingPolicyLoadBalancingUtilization(original["load_balancing_utilization"], d, config) + if err != nil { + return nil, err + } + transformed["loadBalancingUtilization"] = transformedLoadBalancingUtilization + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeAutoscalerAutoscalingPolicyMinReplicas(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyMaxReplicas(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyCpuUtilization(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTarget, err := expandComputeAutoscalerAutoscalingPolicyCpuUtilizationTarget(original["target"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTarget"] = transformedTarget + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeAutoscalerAutoscalingPolicyCpuUtilizationTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyMetric(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedName, err := expandComputeAutoscalerAutoscalingPolicyMetricName(original["name"], d, config) + if err != nil { + return nil, err + } + transformed["metric"] = transformedName + transformedTarget, err := expandComputeAutoscalerAutoscalingPolicyMetricTarget(original["target"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTarget"] = transformedTarget + transformedType, err := expandComputeAutoscalerAutoscalingPolicyMetricType(original["type"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTargetType"] = transformedType + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeAutoscalerAutoscalingPolicyMetricName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyMetricTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyMetricType(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerAutoscalingPolicyLoadBalancingUtilization(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTarget, err := expandComputeAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(original["target"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTarget"] = transformedTarget + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeAutoscalerTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + f, err := parseZonalFieldValue("instanceGroupManagers", v.(string), "project", "zone", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for target: %s", err) + } + return "https://www.googleapis.com/compute/v1/" + f.RelativeLink(), nil +} + +func expandComputeAutoscalerZone(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("zones", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for zone: %s", err) + } + return f.RelativeLink(), nil +} diff --git a/google/resource_compute_autoscaler_test.go b/google/resource_compute_autoscaler_test.go index 079ab300..8f3e49eb 100644 --- a/google/resource_compute_autoscaler_test.go +++ b/google/resource_compute_autoscaler_test.go @@ -2,6 +2,7 @@ package google import ( "fmt" + "strings" "testing" "github.com/hashicorp/terraform/helper/acctest" @@ -111,8 +112,10 @@ func testAccCheckComputeAutoscalerDestroy(s *terraform.State) error { continue } + idParts := strings.Split(rs.Primary.ID, "/") + zone, name := idParts[0], idParts[1] _, err := config.clientCompute.Autoscalers.Get( - config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do() + config.Project, zone, name).Do() if err == nil { return fmt.Errorf("Autoscaler still exists") } @@ -134,13 +137,15 @@ func testAccCheckComputeAutoscalerExists(n string, ascaler *compute.Autoscaler) config := testAccProvider.Meta().(*Config) + idParts := strings.Split(rs.Primary.ID, "/") + zone, name := idParts[0], idParts[1] found, err := config.clientCompute.Autoscalers.Get( - config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do() + config.Project, zone, name).Do() if err != nil { return err } - if found.Name != rs.Primary.ID { + if found.Name != name { return fmt.Errorf("Autoscaler not found") } @@ -163,13 +168,15 @@ func testAccCheckComputeAutoscalerMultifunction(n string) resource.TestCheckFunc config := testAccProvider.Meta().(*Config) + idParts := strings.Split(rs.Primary.ID, "/") + zone, name := idParts[0], idParts[1] found, err := config.clientCompute.Autoscalers.Get( - config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do() + config.Project, zone, name).Do() if err != nil { return err } - if found.Name != rs.Primary.ID { + if found.Name != name { return fmt.Errorf("Autoscaler not found") } @@ -196,8 +203,10 @@ func testAccCheckComputeAutoscalerUpdated(n string, max int64) resource.TestChec config := testAccProvider.Meta().(*Config) + idParts := strings.Split(rs.Primary.ID, "/") + zone, name := idParts[0], idParts[1] ascaler, err := config.clientCompute.Autoscalers.Get( - config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do() + config.Project, zone, name).Do() if err != nil { return err } diff --git a/google/resource_compute_region_autoscaler.go b/google/resource_compute_region_autoscaler.go index a9ed4d25..d0482dc7 100644 --- a/google/resource_compute_region_autoscaler.go +++ b/google/resource_compute_region_autoscaler.go @@ -1,10 +1,29 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + package google import ( "fmt" "log" + "reflect" + "strconv" + "time" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + compute "google.golang.org/api/compute/v1" ) func resourceComputeRegionAutoscaler() *schema.Resource { @@ -13,43 +32,120 @@ func resourceComputeRegionAutoscaler() *schema.Resource { Read: resourceComputeRegionAutoscalerRead, Update: resourceComputeRegionAutoscalerUpdate, Delete: resourceComputeRegionAutoscalerDelete, + Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: resourceComputeRegionAutoscalerImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(240 * time.Second), + Update: schema.DefaultTimeout(240 * time.Second), + Delete: schema.DefaultTimeout(240 * time.Second), }, Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ - Type: schema.TypeString, - ForceNew: true, + "autoscaling_policy": { + Type: schema.TypeList, Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_replicas": { + Type: schema.TypeInt, + Required: true, + }, + "min_replicas": { + Type: schema.TypeInt, + Required: true, + }, + "cooldown_period": { + Type: schema.TypeInt, + Optional: true, + Default: 60, + }, + "cpu_utilization": { + Type: schema.TypeList, + Computed: true, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + "metric": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "target": { + Type: schema.TypeFloat, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"GAUGE", "DELTA_PER_SECOND", "DELTA_PER_MINUTE"}, false), + }, + }, + }, + }, + "load_balancing_utilization": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + }, + }, }, - - "target": &schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateGCPName, + }, + "target": { Type: schema.TypeString, Required: true, }, - - "region": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - - "autoscaling_policy": autoscalingPolicy, - - "description": &schema.Schema{ + "description": { Type: schema.TypeString, Optional: true, }, - - "project": &schema.Schema{ + "region": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, + "creation_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "project": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, - - "self_link": &schema.Schema{ + "self_link": { Type: schema.TypeString, Computed: true, }, @@ -65,34 +161,74 @@ func resourceComputeRegionAutoscalerCreate(d *schema.ResourceData, meta interfac return err } - // Get the region - log.Printf("[DEBUG] Loading region: %s", d.Get("region").(string)) - region, err := config.clientCompute.Regions.Get( - project, d.Get("region").(string)).Do() + obj := make(map[string]interface{}) + nameProp, err := expandComputeRegionAutoscalerName(d.Get("name"), d, config) if err != nil { - return fmt.Errorf( - "Error loading region '%s': %s", d.Get("region").(string), err) + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + descriptionProp, err := expandComputeRegionAutoscalerDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + autoscalingPolicyProp, err := expandComputeRegionAutoscalerAutoscalingPolicy(d.Get("autoscaling_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("autoscaling_policy"); !isEmptyValue(reflect.ValueOf(autoscalingPolicyProp)) && (ok || !reflect.DeepEqual(v, autoscalingPolicyProp)) { + obj["autoscalingPolicy"] = autoscalingPolicyProp + } + targetProp, err := expandComputeRegionAutoscalerTarget(d.Get("target"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(targetProp)) && (ok || !reflect.DeepEqual(v, targetProp)) { + obj["target"] = targetProp + } + regionProp, err := expandComputeRegionAutoscalerRegion(d.Get("region"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) { + obj["region"] = regionProp } - scaler, err := buildAutoscaler(d) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/autoscalers") if err != nil { return err } - op, err := config.clientCompute.RegionAutoscalers.Insert( - project, region.Name, scaler).Do() + log.Printf("[DEBUG] Creating new RegionAutoscaler: %#v", obj) + res, err := Post(config, url, obj) if err != nil { - return fmt.Errorf("Error creating Autoscaler: %s", err) + return fmt.Errorf("Error creating RegionAutoscaler: %s", err) } - // It probably maybe worked, so store the ID now - d.SetId(scaler.Name) + // Store the ID now + id, err := replaceVars(d, config, "{{region}}/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) - err = computeOperationWait(config.clientCompute, op, project, "Creating Autoscaler") + op := &compute.Operation{} + err = Convert(res, op) if err != nil { return err } + waitErr := computeOperationWaitTime( + config.clientCompute, op, project, "Creating RegionAutoscaler", + int(d.Timeout(schema.TimeoutCreate).Minutes())) + + if waitErr != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create RegionAutoscaler: %s", waitErr) + } + + log.Printf("[DEBUG] Finished creating RegionAutoscaler %q: %#v", d.Id(), res) + return resourceComputeRegionAutoscalerRead(d, meta) } @@ -104,31 +240,39 @@ func resourceComputeRegionAutoscalerRead(d *schema.ResourceData, meta interface{ return err } - region, err := getRegion(d, config) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/autoscalers/{{name}}") if err != nil { return err } - scaler, err := config.clientCompute.RegionAutoscalers.Get( - project, region, d.Id()).Do() + res, err := Get(config, url) if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("Autoscaler %q", d.Id())) + return handleNotFoundError(err, d, fmt.Sprintf("ComputeRegionAutoscaler %q", d.Id())) } - if scaler == nil { - log.Printf("[WARN] Removing Autoscaler %q because it's gone", d.Get("name").(string)) - d.SetId("") - return nil + if err := d.Set("creation_timestamp", flattenComputeRegionAutoscalerCreationTimestamp(res["creationTimestamp"])); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) } - - d.Set("self_link", scaler.SelfLink) - d.Set("name", scaler.Name) - d.Set("target", scaler.Target) - d.Set("region", GetResourceNameFromSelfLink(scaler.Region)) - d.Set("description", scaler.Description) - d.Set("project", project) - if scaler.AutoscalingPolicy != nil { - d.Set("autoscaling_policy", flattenAutoscalingPolicy(scaler.AutoscalingPolicy)) + if err := d.Set("name", flattenComputeRegionAutoscalerName(res["name"])); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) + } + if err := d.Set("description", flattenComputeRegionAutoscalerDescription(res["description"])); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) + } + if err := d.Set("autoscaling_policy", flattenComputeRegionAutoscalerAutoscalingPolicy(res["autoscalingPolicy"])); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) + } + if err := d.Set("target", flattenComputeRegionAutoscalerTarget(res["target"])); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) + } + if err := d.Set("region", flattenComputeRegionAutoscalerRegion(res["region"])); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) + } + if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading RegionAutoscaler: %s", err) } return nil @@ -142,23 +286,60 @@ func resourceComputeRegionAutoscalerUpdate(d *schema.ResourceData, meta interfac return err } - region := d.Get("region").(string) + obj := make(map[string]interface{}) + nameProp, err := expandComputeRegionAutoscalerName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + descriptionProp, err := expandComputeRegionAutoscalerDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + autoscalingPolicyProp, err := expandComputeRegionAutoscalerAutoscalingPolicy(d.Get("autoscaling_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("autoscaling_policy"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, autoscalingPolicyProp)) { + obj["autoscalingPolicy"] = autoscalingPolicyProp + } + targetProp, err := expandComputeRegionAutoscalerTarget(d.Get("target"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, targetProp)) { + obj["target"] = targetProp + } + regionProp, err := expandComputeRegionAutoscalerRegion(d.Get("region"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, regionProp)) { + obj["region"] = regionProp + } - scaler, err := buildAutoscaler(d) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/autoscalers?autoscaler={{name}}") if err != nil { return err } - op, err := config.clientCompute.RegionAutoscalers.Update( - project, region, scaler).Do() + log.Printf("[DEBUG] Updating RegionAutoscaler %q: %#v", d.Id(), obj) + res, err := sendRequest(config, "PUT", url, obj) + if err != nil { - return fmt.Errorf("Error updating Autoscaler: %s", err) + return fmt.Errorf("Error updating RegionAutoscaler %q: %s", d.Id(), err) } - // It probably maybe worked, so store the ID now - d.SetId(scaler.Name) + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = computeOperationWaitTime( + config.clientCompute, op, project, "Updating RegionAutoscaler", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) - err = computeOperationWait(config.clientCompute, op, project, "Updating Autoscaler") if err != nil { return err } @@ -174,18 +355,330 @@ func resourceComputeRegionAutoscalerDelete(d *schema.ResourceData, meta interfac return err } - region := d.Get("region").(string) - op, err := config.clientCompute.RegionAutoscalers.Delete( - project, region, d.Id()).Do() - if err != nil { - return fmt.Errorf("Error deleting autoscaler: %s", err) - } - - err = computeOperationWait(config.clientCompute, op, project, "Deleting Autoscaler") + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/autoscalers/{{name}}") if err != nil { return err } - d.SetId("") + log.Printf("[DEBUG] Deleting RegionAutoscaler %q", d.Id()) + res, err := Delete(config, url) + if err != nil { + return handleNotFoundError(err, d, "RegionAutoscaler") + } + + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = computeOperationWaitTime( + config.clientCompute, op, project, "Deleting RegionAutoscaler", + int(d.Timeout(schema.TimeoutDelete).Minutes())) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting RegionAutoscaler %q: %#v", d.Id(), res) return nil } + +func resourceComputeRegionAutoscalerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + parseImportId([]string{"projects/(?P[^/]+)/regions/(?P[^/]+)/autoscalers/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config) + + // Replace import id for the resource id + id, err := replaceVars(d, config, "{{region}}/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenComputeRegionAutoscalerCreationTimestamp(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerName(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerDescription(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicy(v interface{}) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["min_replicas"] = + flattenComputeRegionAutoscalerAutoscalingPolicyMinReplicas(original["minNumReplicas"]) + transformed["max_replicas"] = + flattenComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(original["maxNumReplicas"]) + transformed["cooldown_period"] = + flattenComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(original["coolDownPeriodSec"]) + transformed["cpu_utilization"] = + flattenComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(original["cpuUtilization"]) + transformed["metric"] = + flattenComputeRegionAutoscalerAutoscalingPolicyMetric(original["customMetricUtilizations"]) + transformed["load_balancing_utilization"] = + flattenComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(original["loadBalancingUtilization"]) + return []interface{}{transformed} +} +func flattenComputeRegionAutoscalerAutoscalingPolicyMinReplicas(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(v interface{}) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["target"] = + flattenComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(original["utilizationTarget"]) + return []interface{}{transformed} +} +func flattenComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicyMetric(v interface{}) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed = append(transformed, map[string]interface{}{ + "name": flattenComputeRegionAutoscalerAutoscalingPolicyMetricName(original["metric"]), + "target": flattenComputeRegionAutoscalerAutoscalingPolicyMetricTarget(original["utilizationTarget"]), + "type": flattenComputeRegionAutoscalerAutoscalingPolicyMetricType(original["utilizationTargetType"]), + }) + } + return transformed +} +func flattenComputeRegionAutoscalerAutoscalingPolicyMetricName(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicyMetricTarget(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicyMetricType(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(v interface{}) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["target"] = + flattenComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(original["utilizationTarget"]) + return []interface{}{transformed} +} +func flattenComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerTarget(v interface{}) interface{} { + return v +} + +func flattenComputeRegionAutoscalerRegion(v interface{}) interface{} { + return v +} + +func expandComputeRegionAutoscalerName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicy(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMinReplicas, err := expandComputeRegionAutoscalerAutoscalingPolicyMinReplicas(original["min_replicas"], d, config) + if err != nil { + return nil, err + } + transformed["minNumReplicas"] = transformedMinReplicas + transformedMaxReplicas, err := expandComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(original["max_replicas"], d, config) + if err != nil { + return nil, err + } + transformed["maxNumReplicas"] = transformedMaxReplicas + transformedCooldownPeriod, err := expandComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(original["cooldown_period"], d, config) + if err != nil { + return nil, err + } + transformed["coolDownPeriodSec"] = transformedCooldownPeriod + transformedCpuUtilization, err := expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(original["cpu_utilization"], d, config) + if err != nil { + return nil, err + } + transformed["cpuUtilization"] = transformedCpuUtilization + transformedMetric, err := expandComputeRegionAutoscalerAutoscalingPolicyMetric(original["metric"], d, config) + if err != nil { + return nil, err + } + transformed["customMetricUtilizations"] = transformedMetric + transformedLoadBalancingUtilization, err := expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(original["load_balancing_utilization"], d, config) + if err != nil { + return nil, err + } + transformed["loadBalancingUtilization"] = transformedLoadBalancingUtilization + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyMinReplicas(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(original["target"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTarget"] = transformedTarget + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyMetric(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedName, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricName(original["name"], d, config) + if err != nil { + return nil, err + } + transformed["metric"] = transformedName + transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricTarget(original["target"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTarget"] = transformedTarget + transformedType, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricType(original["type"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTargetType"] = transformedType + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyMetricName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyMetricTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyMetricType(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(original["target"], d, config) + if err != nil { + return nil, err + } + transformed["utilizationTarget"] = transformedTarget + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerTarget(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionAutoscalerRegion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for region: %s", err) + } + return f.RelativeLink(), nil +} diff --git a/google/resource_compute_region_autoscaler_test.go b/google/resource_compute_region_autoscaler_test.go index f295eae5..4a5ee3c8 100644 --- a/google/resource_compute_region_autoscaler_test.go +++ b/google/resource_compute_region_autoscaler_test.go @@ -2,6 +2,7 @@ package google import ( "fmt" + "strings" "testing" "github.com/hashicorp/terraform/helper/acctest" @@ -80,8 +81,9 @@ func testAccCheckComputeRegionAutoscalerDestroy(s *terraform.State) error { continue } - _, err := config.clientCompute.RegionAutoscalers.Get( - config.Project, rs.Primary.Attributes["region"], rs.Primary.ID).Do() + idParts := strings.Split(rs.Primary.ID, "/") + region, name := idParts[0], idParts[1] + _, err := config.clientCompute.RegionAutoscalers.Get(config.Project, region, name).Do() if err == nil { return fmt.Errorf("Autoscaler still exists") } @@ -103,13 +105,14 @@ func testAccCheckComputeRegionAutoscalerExists(n string, ascaler *compute.Autosc config := testAccProvider.Meta().(*Config) - found, err := config.clientCompute.RegionAutoscalers.Get( - config.Project, rs.Primary.Attributes["region"], rs.Primary.ID).Do() + idParts := strings.Split(rs.Primary.ID, "/") + region, name := idParts[0], idParts[1] + found, err := config.clientCompute.RegionAutoscalers.Get(config.Project, region, name).Do() if err != nil { return err } - if found.Name != rs.Primary.ID { + if found.Name != name { return fmt.Errorf("Autoscaler not found") } @@ -132,8 +135,9 @@ func testAccCheckComputeRegionAutoscalerUpdated(n string, max int64) resource.Te config := testAccProvider.Meta().(*Config) - ascaler, err := config.clientCompute.RegionAutoscalers.Get( - config.Project, rs.Primary.Attributes["region"], rs.Primary.ID).Do() + idParts := strings.Split(rs.Primary.ID, "/") + region, name := idParts[0], idParts[1] + ascaler, err := config.clientCompute.RegionAutoscalers.Get(config.Project, region, name).Do() if err != nil { return err } diff --git a/website/docs/r/compute_autoscaler.html.markdown b/website/docs/r/compute_autoscaler.html.markdown index 2ab2ebd2..b8597f38 100644 --- a/website/docs/r/compute_autoscaler.html.markdown +++ b/website/docs/r/compute_autoscaler.html.markdown @@ -1,22 +1,37 @@ --- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- layout: "google" page_title: "Google: google_compute_autoscaler" sidebar_current: "docs-google-compute-autoscaler" description: |- - Manages an Autoscaler within GCE. + Represents an Autoscaler resource. --- # google\_compute\_autoscaler -A Compute Engine Autoscaler automatically adds or removes virtual machines from -a managed instance group based on increases or decreases in load. This allows -your applications to gracefully handle increases in traffic and reduces cost -when the need for resources is lower. You just define the autoscaling policy and -the autoscaler performs automatic scaling based on the measured load. For more -information, see [the official -documentation](https://cloud.google.com/compute/docs/autoscaler/) and -[API](https://cloud.google.com/compute/docs/reference/latest/autoscalers) +Represents an Autoscaler resource. +Autoscalers allow you to automatically scale virtual machine instances in +managed instance groups according to an autoscaling policy that you +define. + +To get more information about Autoscaler, see: + +* [API documentation](https://cloud.google.com/compute/docs/reference/rest/v1/autoscalers) +* How-to Guides + * [Autoscaling Groups of Instances](https://cloud.google.com/compute/docs/autoscaler/) ## Example Usage @@ -79,77 +94,149 @@ resource "google_compute_autoscaler" "foobar" { The following arguments are supported: -* `name` - (Required) The name of the autoscaler. +* `name` - + (Required) + Name of the resource. The name must be 1-63 characters long and match + the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the + first character must be a lowercase letter, and all following + characters must be a dash, lowercase letter, or digit, except the last + character, which cannot be a dash. +* `autoscaling_policy` - + (Required) + The configuration parameters for the autoscaling algorithm. You can + define one or more of the policies for an autoscaler: cpuUtilization, + customMetricUtilizations, and loadBalancingUtilization. -* `target` - (Required) The full URL to the instance group manager whose size we - control. + If none of these are specified, the default will be to autoscale based + on cpuUtilization to 0.6 or 60%. Structure is documented below. +* `target` - + (Required) + URL of the managed instance group that this autoscaler will scale. -* `zone` - (Required) The zone of the target. +The `autoscaling_policy` block supports: +* `min_replicas` - + (Required) + The minimum number of replicas that the autoscaler can scale down + to. This cannot be less than 0. If not provided, autoscaler will + choose a default value depending on maximum number of instances + allowed. +* `max_replicas` - + (Required) + The maximum number of instances that the autoscaler can scale up + to. This is required when creating or updating an autoscaler. The + maximum number of replicas should not be lower than minimal number + of replicas. +* `cooldown_period` - + (Optional) + The number of seconds that the autoscaler should wait before it + starts collecting information from a new instance. This prevents + the autoscaler from collecting information when the instance is + initializing, during which the collected usage would not be + reliable. The default time autoscaler waits is 60 seconds. -* `autoscaling_policy` - (Required) The parameters of the autoscaling - algorithm. Structure is documented below. + Virtual machine initialization times might vary because of + numerous factors. We recommend that you test how long an + instance may take to initialize. To do this, create an instance + and time the startup process. +* `cpu_utilization` - + (Optional) + Defines the CPU utilization policy that allows the autoscaler to + scale based on the average CPU utilization of a managed instance + group. Structure is documented below. +* `metric` - + (Optional) + Defines the CPU utilization policy that allows the autoscaler to + scale based on the average CPU utilization of a managed instance + group. Structure is documented below. +* `load_balancing_utilization` - + (Optional) + Configuration parameters of autoscaling based on a load balancer. Structure is documented below. + The `cpu_utilization` block supports: +* `target` - + (Required) + The target CPU utilization that the autoscaler should maintain. + Must be a float value in the range (0, 1]. If not specified, the + default is 0.6. + + If the CPU level is below the target utilization, the autoscaler + scales down the number of instances until it reaches the minimum + number of instances you specified or until the average CPU of + your instances reaches the target utilization. + + If the average CPU is above the target utilization, the autoscaler + scales up until it reaches the maximum number of instances you + specified or until the average utilization reaches the target + utilization. + + The `metric` block supports: +* `name` - + (Required) + The identifier (type) of the Stackdriver Monitoring metric. + The metric cannot have negative values. + + The metric must have a value type of INT64 or DOUBLE. +* `target` - + (Required) + The target value of the metric that autoscaler should + maintain. This must be a positive value. A utilization + metric scales number of virtual machines handling requests + to increase or decrease proportionally to the metric. + + For example, a good metric to use as a utilizationTarget is + www.googleapis.com/compute/instance/network/received_bytes_count. + The autoscaler will work to keep this value constant for each + of the instances. +* `type` - + (Required) + Defines how target utilization value is expressed for a + Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, + or DELTA_PER_MINUTE. + + The `load_balancing_utilization` block supports: +* `target` - + (Required) + Fraction of backend capacity utilization (set in HTTP(s) load + balancing configuration) that autoscaler should maintain. Must + be a positive float value. If not defined, the default is 0.8. + - - - -* `description` - (Optional) An optional textual description of the instance - group manager. - -* `project` - (Optional) The ID of the project in which the resource belongs. If it - is not provided, the provider project is used. - -The `autoscaling_policy` block contains: - -* `max_replicas` - (Required) The group will never be larger than this. - -* `min_replicas` - (Required) The group will never be smaller than this. - -* `cooldown_period` - (Optional) Period to wait between changes. This should be - at least double the time your instances take to start up. - -* `cpu_utilization` - (Optional) A policy that scales when the cluster's average - CPU is above or below a given threshold. Structure is documented below. - -* `metric` - (Optional) A policy that scales according to Google Cloud - Monitoring metrics Structure is documented below. - -* `load_balancing_utilization` - (Optional) A policy that scales when the load - reaches a proportion of a limit defined in the HTTP load balancer. Structure -is documented below. - -The `cpu_utilization` block contains: - -* `target` - The floating point threshold where CPU utilization should be. E.g. - for 50% one would specify 0.5. - -The `metric` block contains (more documentation -[here](https://cloud.google.com/monitoring/api/metrics)): - -* `name` - The name of the Google Cloud Monitoring metric to follow, e.g. - `compute.googleapis.com/instance/network/received_bytes_count` - -* `type` - Either "cumulative", "delta", or "gauge". - -* `target` - The desired metric value per instance. Must be a positive value. - -The `load_balancing_utilization` block contains: - -* `target` - The floating point threshold where load balancing utilization - should be. E.g. if the load balancer's `maxRatePerInstance` is 10 requests - per second (RPS) then setting this to 0.5 would cause the group to be scaled - such that each instance receives 5 RPS. +* `description` - + (Optional) + An optional description of this resource. +* `zone` - + (Optional) + URL of the zone where the instance group resides. +* `project` (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. ## Attributes Reference -In addition to the arguments listed above, the following computed attributes are -exported: +In addition to the arguments listed above, the following computed attributes are exported: -* `self_link` - The URL of the created resource. +* `creation_timestamp` - + Creation timestamp in RFC3339 text format. +* `self_link` - The URI of the created resource. + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. ## Import -Autoscalers can be imported using the `name`, e.g. +Autoscaler can be imported using any of these accepted formats: ``` -$ terraform import google_compute_autoscaler.foobar scaler +$ terraform import google_compute_autoscaler.default projects/{{project}}/zones/{{zone}}/autoscalers/{{name}} +$ terraform import google_compute_autoscaler.default {{zone}}/{{name}} +$ terraform import google_compute_autoscaler.default {{project}}/{{zone}}/{{name}} +$ terraform import google_compute_autoscaler.default {{name}} ``` diff --git a/website/docs/r/compute_region_autoscaler.html.markdown b/website/docs/r/compute_region_autoscaler.html.markdown index fd178c49..3b072467 100644 --- a/website/docs/r/compute_region_autoscaler.html.markdown +++ b/website/docs/r/compute_region_autoscaler.html.markdown @@ -1,22 +1,37 @@ --- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- layout: "google" page_title: "Google: google_compute_region_autoscaler" sidebar_current: "docs-google-compute-region-autoscaler" description: |- - Manages a Regional Autoscaler within GCE. + Represents an Autoscaler resource. --- # google\_compute\_region\_autoscaler -A Compute Engine Regional Autoscaler automatically adds or removes virtual machines from -a managed instance group based on increases or decreases in load. This allows -your applications to gracefully handle increases in traffic and reduces cost -when the need for resources is lower. You just define the autoscaling policy and -the autoscaler performs automatic scaling based on the measured load. For more -information, see [the official -documentation](https://cloud.google.com/compute/docs/autoscaler/) and -[API](https://cloud.google.com/compute/docs/reference/latest/regionAutoscalers) +Represents an Autoscaler resource. +Autoscalers allow you to automatically scale virtual machine instances in +managed instance groups according to an autoscaling policy that you +define. + +To get more information about RegionAutoscaler, see: + +* [API documentation](https://cloud.google.com/compute/docs/reference/rest/v1/regionAutoscalers) +* How-to Guides + * [Autoscaling Groups of Instances](https://cloud.google.com/compute/docs/autoscaler/) ## Example Usage @@ -79,77 +94,149 @@ resource "google_compute_region_autoscaler" "foobar" { The following arguments are supported: -* `name` - (Required) The name of the autoscaler. +* `name` - + (Required) + Name of the resource. The name must be 1-63 characters long and match + the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the + first character must be a lowercase letter, and all following + characters must be a dash, lowercase letter, or digit, except the last + character, which cannot be a dash. +* `autoscaling_policy` - + (Required) + The configuration parameters for the autoscaling algorithm. You can + define one or more of the policies for an autoscaler: cpuUtilization, + customMetricUtilizations, and loadBalancingUtilization. -* `target` - (Required) The full URL to the instance group manager whose size we - control. + If none of these are specified, the default will be to autoscale based + on cpuUtilization to 0.6 or 60%. Structure is documented below. +* `target` - + (Required) + URL of the managed instance group that this autoscaler will scale. -* `region` - (Required) The region of the target. +The `autoscaling_policy` block supports: +* `min_replicas` - + (Required) + The minimum number of replicas that the autoscaler can scale down + to. This cannot be less than 0. If not provided, autoscaler will + choose a default value depending on maximum number of instances + allowed. +* `max_replicas` - + (Required) + The maximum number of instances that the autoscaler can scale up + to. This is required when creating or updating an autoscaler. The + maximum number of replicas should not be lower than minimal number + of replicas. +* `cooldown_period` - + (Optional) + The number of seconds that the autoscaler should wait before it + starts collecting information from a new instance. This prevents + the autoscaler from collecting information when the instance is + initializing, during which the collected usage would not be + reliable. The default time autoscaler waits is 60 seconds. -* `autoscaling_policy` - (Required) The parameters of the autoscaling - algorithm. Structure is documented below. + Virtual machine initialization times might vary because of + numerous factors. We recommend that you test how long an + instance may take to initialize. To do this, create an instance + and time the startup process. +* `cpu_utilization` - + (Optional) + Defines the CPU utilization policy that allows the autoscaler to + scale based on the average CPU utilization of a managed instance + group. Structure is documented below. +* `metric` - + (Optional) + Defines the CPU utilization policy that allows the autoscaler to + scale based on the average CPU utilization of a managed instance + group. Structure is documented below. +* `load_balancing_utilization` - + (Optional) + Configuration parameters of autoscaling based on a load balancer. Structure is documented below. + The `cpu_utilization` block supports: +* `target` - + (Required) + The target CPU utilization that the autoscaler should maintain. + Must be a float value in the range (0, 1]. If not specified, the + default is 0.6. + + If the CPU level is below the target utilization, the autoscaler + scales down the number of instances until it reaches the minimum + number of instances you specified or until the average CPU of + your instances reaches the target utilization. + + If the average CPU is above the target utilization, the autoscaler + scales up until it reaches the maximum number of instances you + specified or until the average utilization reaches the target + utilization. + + The `metric` block supports: +* `name` - + (Required) + The identifier (type) of the Stackdriver Monitoring metric. + The metric cannot have negative values. + + The metric must have a value type of INT64 or DOUBLE. +* `target` - + (Required) + The target value of the metric that autoscaler should + maintain. This must be a positive value. A utilization + metric scales number of virtual machines handling requests + to increase or decrease proportionally to the metric. + + For example, a good metric to use as a utilizationTarget is + www.googleapis.com/compute/instance/network/received_bytes_count. + The autoscaler will work to keep this value constant for each + of the instances. +* `type` - + (Required) + Defines how target utilization value is expressed for a + Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, + or DELTA_PER_MINUTE. + + The `load_balancing_utilization` block supports: +* `target` - + (Required) + Fraction of backend capacity utilization (set in HTTP(s) load + balancing configuration) that autoscaler should maintain. Must + be a positive float value. If not defined, the default is 0.8. + - - - -* `description` - (Optional) An optional textual description of the instance - group manager. - -* `project` - (Optional) The ID of the project in which the resource belongs. If it - is not provided, the provider project is used. - -The `autoscaling_policy` block contains: - -* `max_replicas` - (Required) The group will never be larger than this. - -* `min_replicas` - (Required) The group will never be smaller than this. - -* `cooldown_period` - (Optional) Period to wait between changes. This should be - at least double the time your instances take to start up. - -* `cpu_utilization` - (Optional) A policy that scales when the cluster's average - CPU is above or below a given threshold. Structure is documented below. - -* `metric` - (Optional) A policy that scales according to Google Cloud - Monitoring metrics Structure is documented below. - -* `load_balancing_utilization` - (Optional) A policy that scales when the load - reaches a proportion of a limit defined in the HTTP load balancer. Structure -is documented below. - -The `cpu_utilization` block contains: - -* `target` - The floating point threshold where CPU utilization should be. E.g. - for 50% one would specify 0.5. - -The `metric` block contains (more documentation -[here](https://cloud.google.com/monitoring/api/metrics)): - -* `name` - The name of the Google Cloud Monitoring metric to follow, e.g. - `compute.googleapis.com/instance/network/received_bytes_count` - -* `type` - Either "cumulative", "delta", or "gauge". - -* `target` - The desired metric value per instance. Must be a positive value. - -The `load_balancing_utilization` block contains: - -* `target` - The floating point threshold where load balancing utilization - should be. E.g. if the load balancer's `maxRatePerInstance` is 10 requests - per second (RPS) then setting this to 0.5 would cause the group to be scaled - such that each instance receives 5 RPS. +* `description` - + (Optional) + An optional description of this resource. +* `region` - + (Optional) + URL of the region where the instance group resides. +* `project` (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. ## Attributes Reference -In addition to the arguments listed above, the following computed attributes are -exported: +In addition to the arguments listed above, the following computed attributes are exported: -* `self_link` - The URL of the created resource. +* `creation_timestamp` - + Creation timestamp in RFC3339 text format. +* `self_link` - The URI of the created resource. + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. ## Import -Autoscalers can be imported using the `name`, e.g. +RegionAutoscaler can be imported using any of these accepted formats: ``` -$ terraform import google_compute_region_autoscaler.foobar scaler +$ terraform import google_compute_region_autoscaler.default projects/{{project}}/regions/{{region}}/autoscalers/{{name}} +$ terraform import google_compute_region_autoscaler.default {{region}}/{{name}} +$ terraform import google_compute_region_autoscaler.default {{project}}/{{region}}/{{name}} +$ terraform import google_compute_region_autoscaler.default {{name}} ```