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