mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-09-06 09:06:44 +00:00
![Paddy Carver](/assets/img/avatar_default.png)
PR #1217 mistakenly updated the Set logic when flattening backends, which caused some cascading errors and wasn't strictly necessary to resolve the issue at hand. This backs out those changes, and instead makes the smallest possible change to resolve the initial error, by separating the logic for flattening regional backends from the logic for flattening global backends.
355 lines
8.3 KiB
Go
355 lines
8.3 KiB
Go
package google
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/hashicorp/terraform/helper/hashcode"
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
"google.golang.org/api/compute/v1"
|
|
)
|
|
|
|
func resourceComputeRegionBackendService() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceComputeRegionBackendServiceCreate,
|
|
Read: resourceComputeRegionBackendServiceRead,
|
|
Update: resourceComputeRegionBackendServiceUpdate,
|
|
Delete: resourceComputeRegionBackendServiceDelete,
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
"name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
ValidateFunc: validateGCPName,
|
|
},
|
|
|
|
"health_checks": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
Required: true,
|
|
MinItems: 1,
|
|
MaxItems: 1,
|
|
},
|
|
|
|
"backend": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Elem: &schema.Resource{
|
|
Schema: map[string]*schema.Schema{
|
|
"group": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
"description": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
},
|
|
},
|
|
Optional: true,
|
|
Set: resourceGoogleComputeRegionBackendServiceBackendHash,
|
|
},
|
|
|
|
"description": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
|
|
"fingerprint": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
|
|
"project": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"protocol": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
},
|
|
|
|
"session_affinity": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
},
|
|
|
|
"region": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"self_link": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
|
|
"timeout_sec": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
Computed: true,
|
|
},
|
|
|
|
"connection_draining_timeout_sec": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
Default: 0,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func resourceComputeRegionBackendServiceCreate(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
|
|
hc := d.Get("health_checks").(*schema.Set).List()
|
|
healthChecks := make([]string, 0, len(hc))
|
|
for _, v := range hc {
|
|
healthChecks = append(healthChecks, v.(string))
|
|
}
|
|
|
|
service := compute.BackendService{
|
|
Name: d.Get("name").(string),
|
|
HealthChecks: healthChecks,
|
|
LoadBalancingScheme: "INTERNAL",
|
|
}
|
|
|
|
var err error
|
|
if v, ok := d.GetOk("backend"); ok {
|
|
service.Backends, err = expandBackends(v.(*schema.Set).List())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if v, ok := d.GetOk("description"); ok {
|
|
service.Description = v.(string)
|
|
}
|
|
|
|
if v, ok := d.GetOk("protocol"); ok {
|
|
service.Protocol = v.(string)
|
|
}
|
|
|
|
if v, ok := d.GetOk("session_affinity"); ok {
|
|
service.SessionAffinity = v.(string)
|
|
}
|
|
|
|
if v, ok := d.GetOk("timeout_sec"); ok {
|
|
service.TimeoutSec = int64(v.(int))
|
|
}
|
|
|
|
if v, ok := d.GetOk("connection_draining_timeout_sec"); ok {
|
|
connectionDraining := &compute.ConnectionDraining{
|
|
DrainingTimeoutSec: int64(v.(int)),
|
|
}
|
|
|
|
service.ConnectionDraining = connectionDraining
|
|
}
|
|
|
|
project, err := getProject(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
region, err := getRegion(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Printf("[DEBUG] Creating new Region Backend Service: %#v", service)
|
|
|
|
op, err := config.clientCompute.RegionBackendServices.Insert(
|
|
project, region, &service).Do()
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating backend service: %s", err)
|
|
}
|
|
|
|
log.Printf("[DEBUG] Waiting for new backend service, operation: %#v", op)
|
|
|
|
d.SetId(service.Name)
|
|
|
|
err = computeOperationWait(config.clientCompute, op, project, "Creating Region Backend Service")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return resourceComputeRegionBackendServiceRead(d, meta)
|
|
}
|
|
|
|
func resourceComputeRegionBackendServiceRead(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
|
|
project, err := getProject(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
region, err := getRegion(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
service, err := config.clientCompute.RegionBackendServices.Get(
|
|
project, region, d.Id()).Do()
|
|
if err != nil {
|
|
return handleNotFoundError(err, d, fmt.Sprintf("Region Backend Service %q", d.Get("name").(string)))
|
|
}
|
|
|
|
d.Set("description", service.Description)
|
|
d.Set("protocol", service.Protocol)
|
|
d.Set("session_affinity", service.SessionAffinity)
|
|
d.Set("timeout_sec", service.TimeoutSec)
|
|
d.Set("connection_draining_timeout_sec", service.ConnectionDraining.DrainingTimeoutSec)
|
|
d.Set("fingerprint", service.Fingerprint)
|
|
d.Set("self_link", service.SelfLink)
|
|
err = d.Set("backend", flattenRegionBackends(service.Backends))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
d.Set("health_checks", service.HealthChecks)
|
|
d.Set("project", project)
|
|
d.Set("region", region)
|
|
|
|
return nil
|
|
}
|
|
|
|
func resourceComputeRegionBackendServiceUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
|
|
project, err := getProject(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
region, err := getRegion(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
hc := d.Get("health_checks").(*schema.Set).List()
|
|
healthChecks := make([]string, 0, len(hc))
|
|
for _, v := range hc {
|
|
healthChecks = append(healthChecks, v.(string))
|
|
}
|
|
|
|
service := compute.BackendService{
|
|
Name: d.Get("name").(string),
|
|
Fingerprint: d.Get("fingerprint").(string),
|
|
HealthChecks: healthChecks,
|
|
LoadBalancingScheme: "INTERNAL",
|
|
}
|
|
|
|
// Optional things
|
|
if v, ok := d.GetOk("backend"); ok {
|
|
service.Backends, err = expandBackends(v.(*schema.Set).List())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if v, ok := d.GetOk("description"); ok {
|
|
service.Description = v.(string)
|
|
}
|
|
if v, ok := d.GetOk("protocol"); ok {
|
|
service.Protocol = v.(string)
|
|
}
|
|
if v, ok := d.GetOk("session_affinity"); ok {
|
|
service.SessionAffinity = v.(string)
|
|
}
|
|
if v, ok := d.GetOk("timeout_sec"); ok {
|
|
service.TimeoutSec = int64(v.(int))
|
|
}
|
|
|
|
if d.HasChange("connection_draining_timeout_sec") {
|
|
connectionDraining := &compute.ConnectionDraining{
|
|
DrainingTimeoutSec: int64(d.Get("connection_draining_timeout_sec").(int)),
|
|
}
|
|
|
|
service.ConnectionDraining = connectionDraining
|
|
}
|
|
|
|
log.Printf("[DEBUG] Updating existing Backend Service %q: %#v", d.Id(), service)
|
|
op, err := config.clientCompute.RegionBackendServices.Update(
|
|
project, region, d.Id(), &service).Do()
|
|
if err != nil {
|
|
return fmt.Errorf("Error updating backend service: %s", err)
|
|
}
|
|
|
|
d.SetId(service.Name)
|
|
|
|
err = computeOperationWait(config.clientCompute, op, project, "Updating Backend Service")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return resourceComputeRegionBackendServiceRead(d, meta)
|
|
}
|
|
|
|
func resourceComputeRegionBackendServiceDelete(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
|
|
project, err := getProject(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
region, err := getRegion(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Printf("[DEBUG] Deleting backend service %s", d.Id())
|
|
op, err := config.clientCompute.RegionBackendServices.Delete(
|
|
project, region, d.Id()).Do()
|
|
if err != nil {
|
|
return fmt.Errorf("Error deleting backend service: %s", err)
|
|
}
|
|
|
|
err = computeOperationWait(config.clientCompute, op, project, "Deleting Backend Service")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
|
|
func resourceGoogleComputeRegionBackendServiceBackendHash(v interface{}) int {
|
|
if v == nil {
|
|
return 0
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
m := v.(map[string]interface{})
|
|
|
|
buf.WriteString(fmt.Sprintf("%s-", m["group"].(string)))
|
|
|
|
if v, ok := m["description"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
|
|
}
|
|
|
|
return hashcode.String(buf.String())
|
|
}
|
|
|
|
func flattenRegionBackends(backends []*compute.Backend) []map[string]interface{} {
|
|
result := make([]map[string]interface{}, 0, len(backends))
|
|
|
|
for _, b := range backends {
|
|
data := make(map[string]interface{})
|
|
|
|
data["description"] = b.Description
|
|
data["group"] = b.Group
|
|
result = append(result, data)
|
|
}
|
|
|
|
return result
|
|
}
|