github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/builtin/providers/google/resource_compute_autoscaler.go (about)

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  	"google.golang.org/api/compute/v1"
     9  	"google.golang.org/api/googleapi"
    10  )
    11  
    12  func resourceComputeAutoscaler() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceComputeAutoscalerCreate,
    15  		Read:   resourceComputeAutoscalerRead,
    16  		Update: resourceComputeAutoscalerUpdate,
    17  		Delete: resourceComputeAutoscalerDelete,
    18  
    19  		Schema: map[string]*schema.Schema{
    20  			"name": &schema.Schema{
    21  				Type:     schema.TypeString,
    22  				ForceNew: true,
    23  				Required: true,
    24  			},
    25  
    26  			"target": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Required: true,
    29  			},
    30  
    31  			"zone": &schema.Schema{
    32  				Type:     schema.TypeString,
    33  				Required: true,
    34  				ForceNew: true,
    35  			},
    36  
    37  			"autoscaling_policy": &schema.Schema{
    38  				Type:     schema.TypeList,
    39  				Optional: true,
    40  				Elem: &schema.Resource{
    41  					Schema: map[string]*schema.Schema{
    42  						"min_replicas": &schema.Schema{
    43  							Type:     schema.TypeInt,
    44  							Required: true,
    45  						},
    46  
    47  						"max_replicas": &schema.Schema{
    48  							Type:     schema.TypeInt,
    49  							Required: true,
    50  						},
    51  
    52  						"cooldown_period": &schema.Schema{
    53  							Type:     schema.TypeInt,
    54  							Optional: true,
    55  							Default:  60,
    56  						},
    57  
    58  						"cpu_utilization": &schema.Schema{
    59  							Type:     schema.TypeList,
    60  							Optional: true,
    61  							Elem: &schema.Resource{
    62  								Schema: map[string]*schema.Schema{
    63  									"target": &schema.Schema{
    64  										Type:     schema.TypeFloat,
    65  										Required: true,
    66  									},
    67  								},
    68  							},
    69  						},
    70  
    71  						"metric": &schema.Schema{
    72  							Type:     schema.TypeList,
    73  							Optional: true,
    74  							Elem: &schema.Resource{
    75  								Schema: map[string]*schema.Schema{
    76  									"name": &schema.Schema{
    77  										Type:     schema.TypeString,
    78  										Required: true,
    79  									},
    80  									"target": &schema.Schema{
    81  										Type:     schema.TypeFloat,
    82  										Required: true,
    83  									},
    84  
    85  									"type": &schema.Schema{
    86  										Type:     schema.TypeString,
    87  										Required: true,
    88  									},
    89  								},
    90  							},
    91  						},
    92  
    93  						"load_balancing_utilization": &schema.Schema{
    94  							Type:     schema.TypeList,
    95  							Optional: true,
    96  							Elem: &schema.Resource{
    97  								Schema: map[string]*schema.Schema{
    98  									"target": &schema.Schema{
    99  										Type:     schema.TypeFloat,
   100  										Required: true,
   101  									},
   102  								},
   103  							},
   104  						},
   105  					},
   106  				},
   107  			},
   108  
   109  			"description": &schema.Schema{
   110  				Type:     schema.TypeString,
   111  				Optional: true,
   112  			},
   113  
   114  			"project": &schema.Schema{
   115  				Type:     schema.TypeString,
   116  				Optional: true,
   117  				ForceNew: true,
   118  			},
   119  
   120  			"self_link": &schema.Schema{
   121  				Type:     schema.TypeString,
   122  				Computed: true,
   123  			},
   124  		},
   125  	}
   126  }
   127  
   128  func buildAutoscaler(d *schema.ResourceData) (*compute.Autoscaler, error) {
   129  	// Build the parameter
   130  	scaler := &compute.Autoscaler{
   131  		Name:   d.Get("name").(string),
   132  		Target: d.Get("target").(string),
   133  	}
   134  
   135  	// Optional fields
   136  	if v, ok := d.GetOk("description"); ok {
   137  		scaler.Description = v.(string)
   138  	}
   139  
   140  	aspCount := d.Get("autoscaling_policy.#").(int)
   141  	if aspCount != 1 {
   142  		return nil, fmt.Errorf("The autoscaler must have exactly one autoscaling_policy, found %d.", aspCount)
   143  	}
   144  
   145  	prefix := "autoscaling_policy.0."
   146  
   147  	scaler.AutoscalingPolicy = &compute.AutoscalingPolicy{
   148  		MaxNumReplicas:    int64(d.Get(prefix + "max_replicas").(int)),
   149  		MinNumReplicas:    int64(d.Get(prefix + "min_replicas").(int)),
   150  		CoolDownPeriodSec: int64(d.Get(prefix + "cooldown_period").(int)),
   151  	}
   152  
   153  	// Check that only one autoscaling policy is defined
   154  
   155  	policyCounter := 0
   156  	if _, ok := d.GetOk(prefix + "cpu_utilization"); ok {
   157  		if d.Get(prefix+"cpu_utilization.0.target").(float64) != 0 {
   158  			cpuUtilCount := d.Get(prefix + "cpu_utilization.#").(int)
   159  			if cpuUtilCount != 1 {
   160  				return nil, fmt.Errorf("The autoscaling_policy must have exactly one cpu_utilization, found %d.", cpuUtilCount)
   161  			}
   162  			policyCounter++
   163  			scaler.AutoscalingPolicy.CpuUtilization = &compute.AutoscalingPolicyCpuUtilization{
   164  				UtilizationTarget: d.Get(prefix + "cpu_utilization.0.target").(float64),
   165  			}
   166  		}
   167  	}
   168  	if _, ok := d.GetOk("autoscaling_policy.0.metric"); ok {
   169  		if d.Get(prefix+"metric.0.name") != "" {
   170  			policyCounter++
   171  			metricCount := d.Get(prefix + "metric.#").(int)
   172  			if metricCount != 1 {
   173  				return nil, fmt.Errorf("The autoscaling_policy must have exactly one metric, found %d.", metricCount)
   174  			}
   175  			scaler.AutoscalingPolicy.CustomMetricUtilizations = []*compute.AutoscalingPolicyCustomMetricUtilization{
   176  				{
   177  					Metric:                d.Get(prefix + "metric.0.name").(string),
   178  					UtilizationTarget:     d.Get(prefix + "metric.0.target").(float64),
   179  					UtilizationTargetType: d.Get(prefix + "metric.0.type").(string),
   180  				},
   181  			}
   182  		}
   183  
   184  	}
   185  	if _, ok := d.GetOk("autoscaling_policy.0.load_balancing_utilization"); ok {
   186  		if d.Get(prefix+"load_balancing_utilization.0.target").(float64) != 0 {
   187  			policyCounter++
   188  			lbuCount := d.Get(prefix + "load_balancing_utilization.#").(int)
   189  			if lbuCount != 1 {
   190  				return nil, fmt.Errorf("The autoscaling_policy must have exactly one load_balancing_utilization, found %d.", lbuCount)
   191  			}
   192  			scaler.AutoscalingPolicy.LoadBalancingUtilization = &compute.AutoscalingPolicyLoadBalancingUtilization{
   193  				UtilizationTarget: d.Get(prefix + "load_balancing_utilization.0.target").(float64),
   194  			}
   195  		}
   196  	}
   197  
   198  	if policyCounter != 1 {
   199  		return nil, fmt.Errorf("One policy must be defined for an autoscaler.")
   200  	}
   201  
   202  	return scaler, nil
   203  }
   204  
   205  func resourceComputeAutoscalerCreate(d *schema.ResourceData, meta interface{}) error {
   206  	config := meta.(*Config)
   207  
   208  	project, err := getProject(d, config)
   209  	if err != nil {
   210  		return err
   211  	}
   212  
   213  	// Get the zone
   214  	log.Printf("[DEBUG] Loading zone: %s", d.Get("zone").(string))
   215  	zone, err := config.clientCompute.Zones.Get(
   216  		project, d.Get("zone").(string)).Do()
   217  	if err != nil {
   218  		return fmt.Errorf(
   219  			"Error loading zone '%s': %s", d.Get("zone").(string), err)
   220  	}
   221  
   222  	scaler, err := buildAutoscaler(d)
   223  	if err != nil {
   224  		return err
   225  	}
   226  
   227  	op, err := config.clientCompute.Autoscalers.Insert(
   228  		project, zone.Name, scaler).Do()
   229  	if err != nil {
   230  		return fmt.Errorf("Error creating Autoscaler: %s", err)
   231  	}
   232  
   233  	// It probably maybe worked, so store the ID now
   234  	d.SetId(scaler.Name)
   235  
   236  	err = computeOperationWaitZone(config, op, zone.Name, "Creating Autoscaler")
   237  	if err != nil {
   238  		return err
   239  	}
   240  
   241  	return resourceComputeAutoscalerRead(d, meta)
   242  }
   243  
   244  func resourceComputeAutoscalerRead(d *schema.ResourceData, meta interface{}) error {
   245  	config := meta.(*Config)
   246  
   247  	project, err := getProject(d, config)
   248  	if err != nil {
   249  		return err
   250  	}
   251  
   252  	zone := d.Get("zone").(string)
   253  	scaler, err := config.clientCompute.Autoscalers.Get(
   254  		project, zone, d.Id()).Do()
   255  	if err != nil {
   256  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
   257  			// The resource doesn't exist anymore
   258  			log.Printf("[WARN] Removing Autoscalar %q because it's gone", d.Get("name").(string))
   259  			d.SetId("")
   260  
   261  			return nil
   262  		}
   263  
   264  		return fmt.Errorf("Error reading Autoscaler: %s", err)
   265  	}
   266  
   267  	d.Set("self_link", scaler.SelfLink)
   268  
   269  	return nil
   270  }
   271  
   272  func resourceComputeAutoscalerUpdate(d *schema.ResourceData, meta interface{}) error {
   273  	config := meta.(*Config)
   274  
   275  	project, err := getProject(d, config)
   276  	if err != nil {
   277  		return err
   278  	}
   279  
   280  	zone := d.Get("zone").(string)
   281  
   282  	scaler, err := buildAutoscaler(d)
   283  	if err != nil {
   284  		return err
   285  	}
   286  
   287  	op, err := config.clientCompute.Autoscalers.Patch(
   288  		project, zone, d.Id(), scaler).Do()
   289  	if err != nil {
   290  		return fmt.Errorf("Error updating Autoscaler: %s", err)
   291  	}
   292  
   293  	// It probably maybe worked, so store the ID now
   294  	d.SetId(scaler.Name)
   295  
   296  	err = computeOperationWaitZone(config, op, zone, "Updating Autoscaler")
   297  	if err != nil {
   298  		return err
   299  	}
   300  
   301  	return resourceComputeAutoscalerRead(d, meta)
   302  }
   303  
   304  func resourceComputeAutoscalerDelete(d *schema.ResourceData, meta interface{}) error {
   305  	config := meta.(*Config)
   306  
   307  	project, err := getProject(d, config)
   308  	if err != nil {
   309  		return err
   310  	}
   311  
   312  	zone := d.Get("zone").(string)
   313  	op, err := config.clientCompute.Autoscalers.Delete(
   314  		project, zone, d.Id()).Do()
   315  	if err != nil {
   316  		return fmt.Errorf("Error deleting autoscaler: %s", err)
   317  	}
   318  
   319  	err = computeOperationWaitZone(config, op, zone, "Deleting Autoscaler")
   320  	if err != nil {
   321  		return err
   322  	}
   323  
   324  	d.SetId("")
   325  	return nil
   326  }