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 }