github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/google/resource_compute_backend_service.go (about) 1 package google 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "regexp" 8 9 "github.com/hashicorp/terraform/helper/hashcode" 10 "github.com/hashicorp/terraform/helper/schema" 11 "google.golang.org/api/compute/v1" 12 "google.golang.org/api/googleapi" 13 ) 14 15 func resourceComputeBackendService() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceComputeBackendServiceCreate, 18 Read: resourceComputeBackendServiceRead, 19 Update: resourceComputeBackendServiceUpdate, 20 Delete: resourceComputeBackendServiceDelete, 21 22 Schema: map[string]*schema.Schema{ 23 "name": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 28 value := v.(string) 29 re := `^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$` 30 if !regexp.MustCompile(re).MatchString(value) { 31 errors = append(errors, fmt.Errorf( 32 "%q (%q) doesn't match regexp %q", k, value, re)) 33 } 34 return 35 }, 36 }, 37 38 "health_checks": &schema.Schema{ 39 Type: schema.TypeSet, 40 Elem: &schema.Schema{Type: schema.TypeString}, 41 Required: true, 42 Set: schema.HashString, 43 }, 44 45 "backend": &schema.Schema{ 46 Type: schema.TypeSet, 47 Elem: &schema.Resource{ 48 Schema: map[string]*schema.Schema{ 49 "group": &schema.Schema{ 50 Type: schema.TypeString, 51 Optional: true, 52 }, 53 "balancing_mode": &schema.Schema{ 54 Type: schema.TypeString, 55 Optional: true, 56 Default: "UTILIZATION", 57 }, 58 "capacity_scaler": &schema.Schema{ 59 Type: schema.TypeFloat, 60 Optional: true, 61 Default: 1, 62 }, 63 "description": &schema.Schema{ 64 Type: schema.TypeString, 65 Optional: true, 66 }, 67 "max_rate": &schema.Schema{ 68 Type: schema.TypeInt, 69 Optional: true, 70 }, 71 "max_rate_per_instance": &schema.Schema{ 72 Type: schema.TypeFloat, 73 Optional: true, 74 }, 75 "max_utilization": &schema.Schema{ 76 Type: schema.TypeFloat, 77 Optional: true, 78 Default: 0.8, 79 }, 80 }, 81 }, 82 Optional: true, 83 Set: resourceGoogleComputeBackendServiceBackendHash, 84 }, 85 86 "description": &schema.Schema{ 87 Type: schema.TypeString, 88 Optional: true, 89 }, 90 91 "enable_cdn": &schema.Schema{ 92 Type: schema.TypeBool, 93 Optional: true, 94 Default: false, 95 }, 96 97 "fingerprint": &schema.Schema{ 98 Type: schema.TypeString, 99 Computed: true, 100 }, 101 102 "port_name": &schema.Schema{ 103 Type: schema.TypeString, 104 Optional: true, 105 Computed: true, 106 }, 107 108 "project": &schema.Schema{ 109 Type: schema.TypeString, 110 Optional: true, 111 ForceNew: true, 112 }, 113 114 "protocol": &schema.Schema{ 115 Type: schema.TypeString, 116 Optional: true, 117 Computed: true, 118 }, 119 120 "region": &schema.Schema{ 121 Type: schema.TypeString, 122 Optional: true, 123 ForceNew: true, 124 }, 125 126 "self_link": &schema.Schema{ 127 Type: schema.TypeString, 128 Computed: true, 129 }, 130 131 "timeout_sec": &schema.Schema{ 132 Type: schema.TypeInt, 133 Optional: true, 134 Computed: true, 135 }, 136 }, 137 } 138 } 139 140 func resourceComputeBackendServiceCreate(d *schema.ResourceData, meta interface{}) error { 141 config := meta.(*Config) 142 143 hc := d.Get("health_checks").(*schema.Set).List() 144 healthChecks := make([]string, 0, len(hc)) 145 for _, v := range hc { 146 healthChecks = append(healthChecks, v.(string)) 147 } 148 149 service := compute.BackendService{ 150 Name: d.Get("name").(string), 151 HealthChecks: healthChecks, 152 } 153 154 if v, ok := d.GetOk("backend"); ok { 155 service.Backends = expandBackends(v.(*schema.Set).List()) 156 } 157 158 if v, ok := d.GetOk("description"); ok { 159 service.Description = v.(string) 160 } 161 162 if v, ok := d.GetOk("port_name"); ok { 163 service.PortName = v.(string) 164 } 165 166 if v, ok := d.GetOk("protocol"); ok { 167 service.Protocol = v.(string) 168 } 169 170 if v, ok := d.GetOk("timeout_sec"); ok { 171 service.TimeoutSec = int64(v.(int)) 172 } 173 174 if v, ok := d.GetOk("enable_cdn"); ok { 175 service.EnableCDN = v.(bool) 176 } 177 178 project, err := getProject(d, config) 179 if err != nil { 180 return err 181 } 182 183 log.Printf("[DEBUG] Creating new Backend Service: %#v", service) 184 op, err := config.clientCompute.BackendServices.Insert( 185 project, &service).Do() 186 if err != nil { 187 return fmt.Errorf("Error creating backend service: %s", err) 188 } 189 190 log.Printf("[DEBUG] Waiting for new backend service, operation: %#v", op) 191 192 d.SetId(service.Name) 193 194 err = computeOperationWaitGlobal(config, op, project, "Creating Backend Service") 195 if err != nil { 196 return err 197 } 198 199 return resourceComputeBackendServiceRead(d, meta) 200 } 201 202 func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{}) error { 203 config := meta.(*Config) 204 205 project, err := getProject(d, config) 206 if err != nil { 207 return err 208 } 209 210 service, err := config.clientCompute.BackendServices.Get( 211 project, d.Id()).Do() 212 if err != nil { 213 if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 { 214 // The resource doesn't exist anymore 215 log.Printf("[WARN] Removing Backend Service %q because it's gone", d.Get("name").(string)) 216 d.SetId("") 217 218 return nil 219 } 220 221 return fmt.Errorf("Error reading service: %s", err) 222 } 223 224 d.Set("description", service.Description) 225 d.Set("enable_cdn", service.EnableCDN) 226 d.Set("port_name", service.PortName) 227 d.Set("protocol", service.Protocol) 228 d.Set("timeout_sec", service.TimeoutSec) 229 d.Set("fingerprint", service.Fingerprint) 230 d.Set("self_link", service.SelfLink) 231 232 d.Set("backend", flattenBackends(service.Backends)) 233 d.Set("health_checks", service.HealthChecks) 234 235 return nil 236 } 237 238 func resourceComputeBackendServiceUpdate(d *schema.ResourceData, meta interface{}) error { 239 config := meta.(*Config) 240 241 project, err := getProject(d, config) 242 if err != nil { 243 return err 244 } 245 246 hc := d.Get("health_checks").(*schema.Set).List() 247 healthChecks := make([]string, 0, len(hc)) 248 for _, v := range hc { 249 healthChecks = append(healthChecks, v.(string)) 250 } 251 252 service := compute.BackendService{ 253 Name: d.Get("name").(string), 254 Fingerprint: d.Get("fingerprint").(string), 255 HealthChecks: healthChecks, 256 } 257 258 // Optional things 259 if v, ok := d.GetOk("backend"); ok { 260 service.Backends = expandBackends(v.(*schema.Set).List()) 261 } 262 if v, ok := d.GetOk("description"); ok { 263 service.Description = v.(string) 264 } 265 if v, ok := d.GetOk("port_name"); ok { 266 service.PortName = v.(string) 267 } 268 if v, ok := d.GetOk("protocol"); ok { 269 service.Protocol = v.(string) 270 } 271 if v, ok := d.GetOk("timeout_sec"); ok { 272 service.TimeoutSec = int64(v.(int)) 273 } 274 275 if d.HasChange("enable_cdn") { 276 service.EnableCDN = d.Get("enable_cdn").(bool) 277 } 278 279 log.Printf("[DEBUG] Updating existing Backend Service %q: %#v", d.Id(), service) 280 op, err := config.clientCompute.BackendServices.Update( 281 project, d.Id(), &service).Do() 282 if err != nil { 283 return fmt.Errorf("Error updating backend service: %s", err) 284 } 285 286 d.SetId(service.Name) 287 288 err = computeOperationWaitGlobal(config, op, project, "Updating Backend Service") 289 if err != nil { 290 return err 291 } 292 293 return resourceComputeBackendServiceRead(d, meta) 294 } 295 296 func resourceComputeBackendServiceDelete(d *schema.ResourceData, meta interface{}) error { 297 config := meta.(*Config) 298 299 project, err := getProject(d, config) 300 if err != nil { 301 return err 302 } 303 304 log.Printf("[DEBUG] Deleting backend service %s", d.Id()) 305 op, err := config.clientCompute.BackendServices.Delete( 306 project, d.Id()).Do() 307 if err != nil { 308 return fmt.Errorf("Error deleting backend service: %s", err) 309 } 310 311 err = computeOperationWaitGlobal(config, op, project, "Deleting Backend Service") 312 if err != nil { 313 return err 314 } 315 316 d.SetId("") 317 return nil 318 } 319 320 func expandBackends(configured []interface{}) []*compute.Backend { 321 backends := make([]*compute.Backend, 0, len(configured)) 322 323 for _, raw := range configured { 324 data := raw.(map[string]interface{}) 325 326 b := compute.Backend{ 327 Group: data["group"].(string), 328 } 329 330 if v, ok := data["balancing_mode"]; ok { 331 b.BalancingMode = v.(string) 332 } 333 if v, ok := data["capacity_scaler"]; ok { 334 b.CapacityScaler = v.(float64) 335 } 336 if v, ok := data["description"]; ok { 337 b.Description = v.(string) 338 } 339 if v, ok := data["max_rate"]; ok { 340 b.MaxRate = int64(v.(int)) 341 } 342 if v, ok := data["max_rate_per_instance"]; ok { 343 b.MaxRatePerInstance = v.(float64) 344 } 345 if v, ok := data["max_utilization"]; ok { 346 b.MaxUtilization = v.(float64) 347 } 348 349 backends = append(backends, &b) 350 } 351 352 return backends 353 } 354 355 func flattenBackends(backends []*compute.Backend) []map[string]interface{} { 356 result := make([]map[string]interface{}, 0, len(backends)) 357 358 for _, b := range backends { 359 data := make(map[string]interface{}) 360 361 data["balancing_mode"] = b.BalancingMode 362 data["capacity_scaler"] = b.CapacityScaler 363 data["description"] = b.Description 364 data["group"] = b.Group 365 data["max_rate"] = b.MaxRate 366 data["max_rate_per_instance"] = b.MaxRatePerInstance 367 data["max_utilization"] = b.MaxUtilization 368 369 result = append(result, data) 370 } 371 372 return result 373 } 374 375 func resourceGoogleComputeBackendServiceBackendHash(v interface{}) int { 376 if v == nil { 377 return 0 378 } 379 380 var buf bytes.Buffer 381 m := v.(map[string]interface{}) 382 383 buf.WriteString(fmt.Sprintf("%s-", m["group"].(string))) 384 385 if v, ok := m["balancing_mode"]; ok { 386 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 387 } 388 if v, ok := m["capacity_scaler"]; ok { 389 buf.WriteString(fmt.Sprintf("%f-", v.(float64))) 390 } 391 if v, ok := m["description"]; ok { 392 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 393 } 394 if v, ok := m["max_rate"]; ok { 395 buf.WriteString(fmt.Sprintf("%d-", int64(v.(int)))) 396 } 397 if v, ok := m["max_rate_per_instance"]; ok { 398 buf.WriteString(fmt.Sprintf("%f-", v.(float64))) 399 } 400 if v, ok := m["max_rate_per_instance"]; ok { 401 buf.WriteString(fmt.Sprintf("%f-", v.(float64))) 402 } 403 404 return hashcode.String(buf.String()) 405 }