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 }