2016-11-18 16:08:26 +00:00
|
|
|
package google
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/helper/hashcode"
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
2016-11-22 21:14:28 +00:00
|
|
|
"google.golang.org/api/compute/v1"
|
2016-11-18 16:08:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func resourceComputeRegionBackendService() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceComputeRegionBackendServiceCreate,
|
|
|
|
Read: resourceComputeRegionBackendServiceRead,
|
|
|
|
Update: resourceComputeRegionBackendServiceUpdate,
|
|
|
|
Delete: resourceComputeRegionBackendServiceDelete,
|
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"name": &schema.Schema{
|
2017-07-07 19:48:29 +00:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
ValidateFunc: validateGCPName,
|
2016-11-18 16:08:26 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
"health_checks": &schema.Schema{
|
|
|
|
Type: schema.TypeSet,
|
|
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
|
|
Set: schema.HashString,
|
2017-06-20 17:26:09 +00:00
|
|
|
Required: true,
|
|
|
|
MinItems: 1,
|
|
|
|
MaxItems: 1,
|
2016-11-18 16:08:26 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
"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,
|
2017-11-28 00:32:20 +00:00
|
|
|
Computed: true,
|
2016-11-18 16:08:26 +00:00
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"protocol": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
2017-01-18 00:32:58 +00:00
|
|
|
"session_affinity": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
2016-11-18 16:08:26 +00:00
|
|
|
"region": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
2017-11-28 00:32:20 +00:00
|
|
|
Computed: true,
|
2016-11-18 16:08:26 +00:00
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"self_link": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"timeout_sec": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
2017-06-13 21:08:15 +00:00
|
|
|
|
|
|
|
"connection_draining_timeout_sec": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Default: 0,
|
|
|
|
},
|
2016-11-18 16:08:26 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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{
|
2016-12-01 01:44:13 +00:00
|
|
|
Name: d.Get("name").(string),
|
|
|
|
HealthChecks: healthChecks,
|
|
|
|
LoadBalancingScheme: "INTERNAL",
|
2016-11-18 16:08:26 +00:00
|
|
|
}
|
|
|
|
|
2017-10-12 16:21:35 +00:00
|
|
|
var err error
|
2016-11-18 16:08:26 +00:00
|
|
|
if v, ok := d.GetOk("backend"); ok {
|
2017-10-12 16:21:35 +00:00
|
|
|
service.Backends, err = expandBackends(v.(*schema.Set).List())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-11-18 16:08:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if v, ok := d.GetOk("description"); ok {
|
|
|
|
service.Description = v.(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, ok := d.GetOk("protocol"); ok {
|
|
|
|
service.Protocol = v.(string)
|
|
|
|
}
|
|
|
|
|
2017-01-18 00:32:58 +00:00
|
|
|
if v, ok := d.GetOk("session_affinity"); ok {
|
|
|
|
service.SessionAffinity = v.(string)
|
|
|
|
}
|
|
|
|
|
2016-11-18 16:08:26 +00:00
|
|
|
if v, ok := d.GetOk("timeout_sec"); ok {
|
|
|
|
service.TimeoutSec = int64(v.(int))
|
|
|
|
}
|
|
|
|
|
2017-06-13 21:08:15 +00:00
|
|
|
if v, ok := d.GetOk("connection_draining_timeout_sec"); ok {
|
|
|
|
connectionDraining := &compute.ConnectionDraining{
|
|
|
|
DrainingTimeoutSec: int64(v.(int)),
|
|
|
|
}
|
|
|
|
|
|
|
|
service.ConnectionDraining = connectionDraining
|
|
|
|
}
|
|
|
|
|
2016-11-18 16:08:26 +00:00
|
|
|
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)
|
|
|
|
|
2016-11-22 21:14:28 +00:00
|
|
|
op, err := config.clientCompute.RegionBackendServices.Insert(
|
2016-11-18 16:08:26 +00:00
|
|
|
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)
|
|
|
|
|
2017-10-13 22:36:03 +00:00
|
|
|
err = computeOperationWait(config.clientCompute, op, project, "Creating Region Backend Service")
|
2016-11-18 16:08:26 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-11-22 21:14:28 +00:00
|
|
|
service, err := config.clientCompute.RegionBackendServices.Get(
|
2016-11-18 16:08:26 +00:00
|
|
|
project, region, d.Id()).Do()
|
|
|
|
if err != nil {
|
2017-05-09 23:00:47 +00:00
|
|
|
return handleNotFoundError(err, d, fmt.Sprintf("Region Backend Service %q", d.Get("name").(string)))
|
2016-11-18 16:08:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
d.Set("description", service.Description)
|
|
|
|
d.Set("protocol", service.Protocol)
|
2017-01-18 00:32:58 +00:00
|
|
|
d.Set("session_affinity", service.SessionAffinity)
|
2016-11-18 16:08:26 +00:00
|
|
|
d.Set("timeout_sec", service.TimeoutSec)
|
2017-06-13 21:08:15 +00:00
|
|
|
d.Set("connection_draining_timeout_sec", service.ConnectionDraining.DrainingTimeoutSec)
|
2016-11-18 16:08:26 +00:00
|
|
|
d.Set("fingerprint", service.Fingerprint)
|
|
|
|
d.Set("self_link", service.SelfLink)
|
|
|
|
d.Set("backend", flattenBackends(service.Backends))
|
|
|
|
d.Set("health_checks", service.HealthChecks)
|
2017-11-28 00:32:20 +00:00
|
|
|
d.Set("project", project)
|
|
|
|
d.Set("region", region)
|
2016-11-18 16:08:26 +00:00
|
|
|
|
|
|
|
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{
|
2016-12-01 01:44:13 +00:00
|
|
|
Name: d.Get("name").(string),
|
|
|
|
Fingerprint: d.Get("fingerprint").(string),
|
|
|
|
HealthChecks: healthChecks,
|
|
|
|
LoadBalancingScheme: "INTERNAL",
|
2016-11-18 16:08:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Optional things
|
|
|
|
if v, ok := d.GetOk("backend"); ok {
|
2017-10-12 16:21:35 +00:00
|
|
|
service.Backends, err = expandBackends(v.(*schema.Set).List())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-11-18 16:08:26 +00:00
|
|
|
}
|
|
|
|
if v, ok := d.GetOk("description"); ok {
|
|
|
|
service.Description = v.(string)
|
|
|
|
}
|
|
|
|
if v, ok := d.GetOk("protocol"); ok {
|
|
|
|
service.Protocol = v.(string)
|
|
|
|
}
|
2017-01-18 00:32:58 +00:00
|
|
|
if v, ok := d.GetOk("session_affinity"); ok {
|
|
|
|
service.SessionAffinity = v.(string)
|
|
|
|
}
|
2016-11-18 16:08:26 +00:00
|
|
|
if v, ok := d.GetOk("timeout_sec"); ok {
|
|
|
|
service.TimeoutSec = int64(v.(int))
|
|
|
|
}
|
|
|
|
|
2017-06-13 21:08:15 +00:00
|
|
|
if d.HasChange("connection_draining_timeout_sec") {
|
|
|
|
connectionDraining := &compute.ConnectionDraining{
|
|
|
|
DrainingTimeoutSec: int64(d.Get("connection_draining_timeout_sec").(int)),
|
|
|
|
}
|
|
|
|
|
|
|
|
service.ConnectionDraining = connectionDraining
|
|
|
|
}
|
|
|
|
|
2016-11-18 16:08:26 +00:00
|
|
|
log.Printf("[DEBUG] Updating existing Backend Service %q: %#v", d.Id(), service)
|
2016-11-22 21:14:28 +00:00
|
|
|
op, err := config.clientCompute.RegionBackendServices.Update(
|
2016-11-18 16:08:26 +00:00
|
|
|
project, region, d.Id(), &service).Do()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error updating backend service: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId(service.Name)
|
|
|
|
|
2017-10-13 22:36:03 +00:00
|
|
|
err = computeOperationWait(config.clientCompute, op, project, "Updating Backend Service")
|
2016-11-18 16:08:26 +00:00
|
|
|
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())
|
2016-11-22 21:14:28 +00:00
|
|
|
op, err := config.clientCompute.RegionBackendServices.Delete(
|
2016-11-18 16:08:26 +00:00
|
|
|
project, region, d.Id()).Do()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error deleting backend service: %s", err)
|
|
|
|
}
|
|
|
|
|
2017-10-13 22:36:03 +00:00
|
|
|
err = computeOperationWait(config.clientCompute, op, project, "Deleting Backend Service")
|
2016-11-18 16:08:26 +00:00
|
|
|
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())
|
|
|
|
}
|