diff --git a/CHANGELOG.md b/CHANGELOG.md index 4623ef61e..7d7d3c8a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,8 +27,10 @@ IMPROVEMENTS: BUG FIXES: * core: Fix problems referencing list attributes in interpolations [GH-2157] + * core: don't error on computed value during input walk [GH-2988] * provider/google: Crashes with interface conversion in GCE Instance Template [GH-3027] * provider/google: Convert int to int64 when building the GKE cluster.NodeConfig struct [GH-2978] + * provider/google: google_compute_instance_template.network_interface.network should be a URL [GH-3226] * provider/aws: Retry creation of `aws_ecs_service` if IAM policy isn't ready yet [GH-3061] * provider/aws: Fix issue with mixed capitalization for RDS Instances [GH-3053] * provider/aws: Fix issue with RDS to allow major version upgrades [GH-3053] @@ -40,6 +42,8 @@ BUG FIXES: * provider/aws: Allow `weight = 0` in Route53 records [GH-3196] * provider/openstack: add state 'downloading' to list of expected states in `blockstorage_volume_v1` creation [GH-2866] + * provider/openstack: remove security groups (by name) before adding security + groups (by id) [GH-2008] ## 0.6.3 (August 11, 2015) diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpc.go b/builtin/providers/cloudstack/resource_cloudstack_vpc.go index 8fe132d94..4cc07d7b6 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_vpc.go +++ b/builtin/providers/cloudstack/resource_cloudstack_vpc.go @@ -40,6 +40,12 @@ func resourceCloudStackVPC() *schema.Resource { ForceNew: true, }, + "network_domain": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "project": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -79,7 +85,19 @@ func resourceCloudStackVPCCreate(d *schema.ResourceData, meta interface{}) error } // Create a new parameter struct - p := cs.VPC.NewCreateVPCParams(d.Get("cidr").(string), displaytext.(string), name, vpcofferingid, zoneid) + p := cs.VPC.NewCreateVPCParams( + d.Get("cidr").(string), + displaytext.(string), + name, + vpcofferingid, + zoneid, + ) + + // If there is a network domain supplied, make sure to add it to the request + if networkDomain, ok := d.GetOk("network_domain"); ok { + // Set the network domain + p.SetNetworkdomain(networkDomain.(string)) + } // If there is a project supplied, we retrieve and set the project id if project, ok := d.GetOk("project"); ok { @@ -122,6 +140,7 @@ func resourceCloudStackVPCRead(d *schema.ResourceData, meta interface{}) error { d.Set("name", v.Name) d.Set("display_text", v.Displaytext) d.Set("cidr", v.Cidr) + d.Set("network_domain", v.Networkdomain) // Get the VPC offering details o, _, err := cs.VPC.GetVPCOfferingByID(v.Vpcofferingid) diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go b/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go index 011358a95..7c1d1492e 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go @@ -76,6 +76,10 @@ func testAccCheckCloudStackVPCAttributes( return fmt.Errorf("Bad VPC CIDR: %s", vpc.Cidr) } + if vpc.Networkdomain != "terraform-domain" { + return fmt.Errorf("Bad network domain: %s", vpc.Networkdomain) + } + return nil } } @@ -107,6 +111,7 @@ resource "cloudstack_vpc" "foo" { display_text = "terraform-vpc-text" cidr = "%s" vpc_offering = "%s" + network_domain = "terraform-domain" zone = "%s" }`, CLOUDSTACK_VPC_CIDR_1, diff --git a/builtin/providers/google/compute_operation.go b/builtin/providers/google/compute_operation.go new file mode 100644 index 000000000..987e983b4 --- /dev/null +++ b/builtin/providers/google/compute_operation.go @@ -0,0 +1,158 @@ +package google + +import ( + "bytes" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform/helper/resource" + "google.golang.org/api/compute/v1" +) + +// OperationWaitType is an enum specifying what type of operation +// we're waiting on. +type ComputeOperationWaitType byte + +const ( + ComputeOperationWaitInvalid ComputeOperationWaitType = iota + ComputeOperationWaitGlobal + ComputeOperationWaitRegion + ComputeOperationWaitZone +) + +type ComputeOperationWaiter struct { + Service *compute.Service + Op *compute.Operation + Project string + Region string + Type ComputeOperationWaitType + Zone string +} + +func (w *ComputeOperationWaiter) RefreshFunc() resource.StateRefreshFunc { + return func() (interface{}, string, error) { + var op *compute.Operation + var err error + + switch w.Type { + case ComputeOperationWaitGlobal: + op, err = w.Service.GlobalOperations.Get( + w.Project, w.Op.Name).Do() + case ComputeOperationWaitRegion: + op, err = w.Service.RegionOperations.Get( + w.Project, w.Region, w.Op.Name).Do() + case ComputeOperationWaitZone: + op, err = w.Service.ZoneOperations.Get( + w.Project, w.Zone, w.Op.Name).Do() + default: + return nil, "bad-type", fmt.Errorf( + "Invalid wait type: %#v", w.Type) + } + + if err != nil { + return nil, "", err + } + + log.Printf("[DEBUG] Got %q when asking for operation %q", op.Status, w.Op.Name) + + return op, op.Status, nil + } +} + +func (w *ComputeOperationWaiter) Conf() *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{"PENDING", "RUNNING"}, + Target: "DONE", + Refresh: w.RefreshFunc(), + } +} + +// ComputeOperationError wraps compute.OperationError and implements the +// error interface so it can be returned. +type ComputeOperationError compute.OperationError + +func (e ComputeOperationError) Error() string { + var buf bytes.Buffer + + for _, err := range e.Errors { + buf.WriteString(err.Message + "\n") + } + + return buf.String() +} + +func computeOperationWaitGlobal(config *Config, op *compute.Operation, activity string) error { + w := &ComputeOperationWaiter{ + Service: config.clientCompute, + Op: op, + Project: config.Project, + Type: ComputeOperationWaitGlobal, + } + + state := w.Conf() + state.Delay = 10 * time.Second + state.Timeout = 4 * time.Minute + state.MinTimeout = 2 * time.Second + opRaw, err := state.WaitForState() + if err != nil { + return fmt.Errorf("Error waiting for %s: %s", activity, err) + } + + op = opRaw.(*compute.Operation) + if op.Error != nil { + return ComputeOperationError(*op.Error) + } + + return nil +} + +func computeOperationWaitRegion(config *Config, op *compute.Operation, region, activity string) error { + w := &ComputeOperationWaiter{ + Service: config.clientCompute, + Op: op, + Project: config.Project, + Type: ComputeOperationWaitRegion, + Region: region, + } + + state := w.Conf() + state.Delay = 10 * time.Second + state.Timeout = 4 * time.Minute + state.MinTimeout = 2 * time.Second + opRaw, err := state.WaitForState() + if err != nil { + return fmt.Errorf("Error waiting for %s: %s", activity, err) + } + + op = opRaw.(*compute.Operation) + if op.Error != nil { + return ComputeOperationError(*op.Error) + } + + return nil +} + +func computeOperationWaitZone(config *Config, op *compute.Operation, zone, activity string) error { + w := &ComputeOperationWaiter{ + Service: config.clientCompute, + Op: op, + Project: config.Project, + Zone: zone, + Type: ComputeOperationWaitZone, + } + state := w.Conf() + state.Delay = 10 * time.Second + state.Timeout = 4 * time.Minute + state.MinTimeout = 2 * time.Second + opRaw, err := state.WaitForState() + if err != nil { + return fmt.Errorf("Error waiting for %s: %s", activity, err) + } + op = opRaw.(*compute.Operation) + if op.Error != nil { + // Return the error + return ComputeOperationError(*op.Error) + } + return nil +} diff --git a/builtin/providers/google/operation.go b/builtin/providers/google/operation.go deleted file mode 100644 index 0971e3f5b..000000000 --- a/builtin/providers/google/operation.go +++ /dev/null @@ -1,82 +0,0 @@ -package google - -import ( - "bytes" - "fmt" - "log" - - "github.com/hashicorp/terraform/helper/resource" - "google.golang.org/api/compute/v1" -) - -// OperationWaitType is an enum specifying what type of operation -// we're waiting on. -type OperationWaitType byte - -const ( - OperationWaitInvalid OperationWaitType = iota - OperationWaitGlobal - OperationWaitRegion - OperationWaitZone -) - -type OperationWaiter struct { - Service *compute.Service - Op *compute.Operation - Project string - Region string - Type OperationWaitType - Zone string -} - -func (w *OperationWaiter) RefreshFunc() resource.StateRefreshFunc { - return func() (interface{}, string, error) { - var op *compute.Operation - var err error - - switch w.Type { - case OperationWaitGlobal: - op, err = w.Service.GlobalOperations.Get( - w.Project, w.Op.Name).Do() - case OperationWaitRegion: - op, err = w.Service.RegionOperations.Get( - w.Project, w.Region, w.Op.Name).Do() - case OperationWaitZone: - op, err = w.Service.ZoneOperations.Get( - w.Project, w.Zone, w.Op.Name).Do() - default: - return nil, "bad-type", fmt.Errorf( - "Invalid wait type: %#v", w.Type) - } - - if err != nil { - return nil, "", err - } - - log.Printf("[DEBUG] Got %q when asking for operation %q", op.Status, w.Op.Name) - - return op, op.Status, nil - } -} - -func (w *OperationWaiter) Conf() *resource.StateChangeConf { - return &resource.StateChangeConf{ - Pending: []string{"PENDING", "RUNNING"}, - Target: "DONE", - Refresh: w.RefreshFunc(), - } -} - -// OperationError wraps compute.OperationError and implements the -// error interface so it can be returned. -type OperationError compute.OperationError - -func (e OperationError) Error() string { - var buf bytes.Buffer - - for _, err := range e.Errors { - buf.WriteString(err.Message + "\n") - } - - return buf.String() -} diff --git a/builtin/providers/google/resource_compute_address.go b/builtin/providers/google/resource_compute_address.go index 721d67d14..0027df230 100644 --- a/builtin/providers/google/resource_compute_address.go +++ b/builtin/providers/google/resource_compute_address.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" @@ -65,28 +64,9 @@ func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) erro // It probably maybe worked, so store the ID now d.SetId(addr.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Region: region, - Type: OperationWaitRegion, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitRegion(config, op, region, "Creating Address") if err != nil { - return fmt.Errorf("Error waiting for address to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeAddressRead(d, meta) @@ -128,25 +108,9 @@ func resourceComputeAddressDelete(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error deleting address: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Region: region, - Type: OperationWaitRegion, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitRegion(config, op, region, "Deleting Address") if err != nil { - return fmt.Errorf("Error waiting for address to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_autoscaler.go b/builtin/providers/google/resource_compute_autoscaler.go index 10b7c84ef..8539c62b3 100644 --- a/builtin/providers/google/resource_compute_autoscaler.go +++ b/builtin/providers/google/resource_compute_autoscaler.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" @@ -224,28 +223,9 @@ func resourceComputeAutoscalerCreate(d *schema.ResourceData, meta interface{}) e // It probably maybe worked, so store the ID now d.SetId(scaler.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitZone, - Zone: zone.Name, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitZone(config, op, zone.Name, "Creating Autoscaler") if err != nil { - return fmt.Errorf("Error waiting for Autoscaler to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeAutoscalerRead(d, meta) @@ -292,25 +272,9 @@ func resourceComputeAutoscalerUpdate(d *schema.ResourceData, meta interface{}) e // It probably maybe worked, so store the ID now d.SetId(scaler.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitZone, - Zone: zone, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitZone(config, op, zone, "Updating Autoscaler") if err != nil { - return fmt.Errorf("Error waiting for Autoscaler to update: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeAutoscalerRead(d, meta) @@ -326,25 +290,9 @@ func resourceComputeAutoscalerDelete(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error deleting autoscaler: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitZone, - Zone: zone, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitZone(config, op, zone, "Deleting Autoscaler") if err != nil { - return fmt.Errorf("Error waiting for Autoscaler to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_backend_service.go b/builtin/providers/google/resource_compute_backend_service.go index a8826f8e4..cbd722d38 100644 --- a/builtin/providers/google/resource_compute_backend_service.go +++ b/builtin/providers/google/resource_compute_backend_service.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "regexp" - "time" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" @@ -165,28 +164,9 @@ func resourceComputeBackendServiceCreate(d *schema.ResourceData, meta interface{ d.SetId(service.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Region: config.Region, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Creating Backend Service") if err != nil { - return fmt.Errorf("Error waiting for backend service to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeBackendServiceRead(d, meta) @@ -261,25 +241,9 @@ func resourceComputeBackendServiceUpdate(d *schema.ResourceData, meta interface{ d.SetId(service.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Region: config.Region, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Updating Backend Service") if err != nil { - return fmt.Errorf("Error waiting for backend service to update: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeBackendServiceRead(d, meta) @@ -295,25 +259,9 @@ func resourceComputeBackendServiceDelete(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error deleting backend service: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Region: config.Region, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Deleting Backend Service") if err != nil { - return fmt.Errorf("Error waiting for backend service to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_disk.go b/builtin/providers/google/resource_compute_disk.go index 7202e45d9..1118702d6 100644 --- a/builtin/providers/google/resource_compute_disk.go +++ b/builtin/providers/google/resource_compute_disk.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" @@ -128,37 +127,10 @@ func resourceComputeDiskCreate(d *schema.ResourceData, meta interface{}) error { // It probably maybe worked, so store the ID now d.SetId(disk.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Zone: d.Get("zone").(string), - Type: OperationWaitZone, - } - state := w.Conf() - - if disk.SourceSnapshot != "" { - //creating disk from snapshot takes some time - state.Timeout = 10 * time.Minute - } else { - state.Timeout = 2 * time.Minute - } - - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Creating Disk") if err != nil { - return fmt.Errorf("Error waiting for disk to create: %s", err) + return err } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) - } - return resourceComputeDiskRead(d, meta) } @@ -193,25 +165,10 @@ func resourceComputeDiskDelete(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error deleting disk: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Zone: d.Get("zone").(string), - Type: OperationWaitZone, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + zone := d.Get("zone").(string) + err = computeOperationWaitZone(config, op, zone, "Creating Disk") if err != nil { - return fmt.Errorf("Error waiting for disk to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_firewall.go b/builtin/providers/google/resource_compute_firewall.go index 2a2433a87..1cec2c826 100644 --- a/builtin/providers/google/resource_compute_firewall.go +++ b/builtin/providers/google/resource_compute_firewall.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "sort" - "time" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" @@ -135,27 +134,9 @@ func resourceComputeFirewallCreate(d *schema.ResourceData, meta interface{}) err // It probably maybe worked, so store the ID now d.SetId(firewall.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Creating Firewall") if err != nil { - return fmt.Errorf("Error waiting for firewall to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeFirewallRead(d, meta) @@ -198,24 +179,9 @@ func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error updating firewall: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Updating Firewall") if err != nil { - return fmt.Errorf("Error waiting for firewall to update: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.Partial(false) @@ -233,24 +199,9 @@ func resourceComputeFirewallDelete(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error deleting firewall: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Deleting Firewall") if err != nil { - return fmt.Errorf("Error waiting for firewall to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_forwarding_rule.go b/builtin/providers/google/resource_compute_forwarding_rule.go index 0c905ead7..ac4851e51 100644 --- a/builtin/providers/google/resource_compute_forwarding_rule.go +++ b/builtin/providers/google/resource_compute_forwarding_rule.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" @@ -94,28 +93,9 @@ func resourceComputeForwardingRuleCreate(d *schema.ResourceData, meta interface{ // It probably maybe worked, so store the ID now d.SetId(frule.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Region: region, - Project: config.Project, - Type: OperationWaitRegion, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitRegion(config, op, region, "Creating Fowarding Rule") if err != nil { - return fmt.Errorf("Error waiting for ForwardingRule to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeForwardingRuleRead(d, meta) @@ -137,29 +117,11 @@ func resourceComputeForwardingRuleUpdate(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error updating target: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Region: region, - Project: config.Project, - Type: OperationWaitRegion, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitRegion(config, op, region, "Updating Forwarding Rule") if err != nil { - return fmt.Errorf("Error waiting for ForwardingRule to update target: %s", err) + return err } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - // Return the error - return OperationError(*op.Error) - } d.SetPartial("target") } @@ -206,25 +168,9 @@ func resourceComputeForwardingRuleDelete(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error deleting ForwardingRule: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Region: region, - Project: config.Project, - Type: OperationWaitRegion, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitRegion(config, op, region, "Deleting Forwarding Rule") if err != nil { - return fmt.Errorf("Error waiting for ForwardingRule to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_http_health_check.go b/builtin/providers/google/resource_compute_http_health_check.go index 4dfe3a03d..c53267afd 100644 --- a/builtin/providers/google/resource_compute_http_health_check.go +++ b/builtin/providers/google/resource_compute_http_health_check.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" @@ -121,27 +120,9 @@ func resourceComputeHttpHealthCheckCreate(d *schema.ResourceData, meta interface // It probably maybe worked, so store the ID now d.SetId(hchk.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Creating Http Health Check") if err != nil { - return fmt.Errorf("Error waiting for HttpHealthCheck to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeHttpHealthCheckRead(d, meta) @@ -190,27 +171,9 @@ func resourceComputeHttpHealthCheckUpdate(d *schema.ResourceData, meta interface // It probably maybe worked, so store the ID now d.SetId(hchk.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Updating Http Health Check") if err != nil { - return fmt.Errorf("Error waiting for HttpHealthCheck to patch: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeHttpHealthCheckRead(d, meta) @@ -254,24 +217,9 @@ func resourceComputeHttpHealthCheckDelete(d *schema.ResourceData, meta interface return fmt.Errorf("Error deleting HttpHealthCheck: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Deleting Http Health Check") if err != nil { - return fmt.Errorf("Error waiting for HttpHealthCheck to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_instance.go b/builtin/providers/google/resource_compute_instance.go index 2a03a7f94..987964641 100644 --- a/builtin/providers/google/resource_compute_instance.go +++ b/builtin/providers/google/resource_compute_instance.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" @@ -273,32 +272,6 @@ func getInstance(config *Config, d *schema.ResourceData) (*compute.Instance, err return instance, nil } -func resourceOperationWaitZone( - config *Config, op *compute.Operation, zone string, activity string) error { - - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Zone: zone, - Type: OperationWaitZone, - } - state := w.Conf() - state.Delay = 10 * time.Second - state.Timeout = 10 * time.Minute - state.MinTimeout = 2 * time.Second - opRaw, err := state.WaitForState() - if err != nil { - return fmt.Errorf("Error waiting for %s: %s", activity, err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) - } - return nil -} - func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -521,7 +494,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err d.SetId(instance.Name) // Wait for the operation to complete - waitErr := resourceOperationWaitZone(config, op, zone.Name, "instance to create") + waitErr := computeOperationWaitZone(config, op, zone.Name, "instance to create") if waitErr != nil { // The resource didn't actually create d.SetId("") @@ -703,7 +676,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error updating metadata: %s", err) } - opErr := resourceOperationWaitZone(config, op, zone, "metadata to update") + opErr := computeOperationWaitZone(config, op, zone, "metadata to update") if opErr != nil { return opErr } @@ -723,7 +696,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error updating tags: %s", err) } - opErr := resourceOperationWaitZone(config, op, zone, "tags to update") + opErr := computeOperationWaitZone(config, op, zone, "tags to update") if opErr != nil { return opErr } @@ -764,7 +737,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error deleting old access_config: %s", err) } - opErr := resourceOperationWaitZone(config, op, zone, "old access_config to delete") + opErr := computeOperationWaitZone(config, op, zone, "old access_config to delete") if opErr != nil { return opErr } @@ -783,7 +756,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error adding new access_config: %s", err) } - opErr := resourceOperationWaitZone(config, op, zone, "new access_config to add") + opErr := computeOperationWaitZone(config, op, zone, "new access_config to add") if opErr != nil { return opErr } @@ -809,7 +782,7 @@ func resourceComputeInstanceDelete(d *schema.ResourceData, meta interface{}) err } // Wait for the operation to complete - opErr := resourceOperationWaitZone(config, op, zone, "instance to delete") + opErr := computeOperationWaitZone(config, op, zone, "instance to delete") if opErr != nil { return opErr } diff --git a/builtin/providers/google/resource_compute_instance_group_manager.go b/builtin/providers/google/resource_compute_instance_group_manager.go index 9651c935f..ed48b26d5 100644 --- a/builtin/providers/google/resource_compute_instance_group_manager.go +++ b/builtin/providers/google/resource_compute_instance_group_manager.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" @@ -82,26 +81,6 @@ func resourceComputeInstanceGroupManager() *schema.Resource { } } -func waitOpZone(config *Config, op *compute.Operation, zone string, - resource string, action string) (*compute.Operation, error) { - - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Zone: zone, - Type: OperationWaitZone, - } - state := w.Conf() - state.Timeout = 8 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() - if err != nil { - return nil, fmt.Errorf("Error waiting for %s to %s: %s", resource, action, err) - } - return opRaw.(*compute.Operation), nil -} - func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -143,16 +122,10 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte d.SetId(manager.Name) // Wait for the operation to complete - op, err = waitOpZone(config, op, d.Get("zone").(string), "InstanceGroupManager", "create") + err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Creating InstanceGroupManager") if err != nil { return err } - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - // Return the error - return OperationError(*op.Error) - } return resourceComputeInstanceGroupManagerRead(d, meta) } @@ -208,13 +181,10 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte } // Wait for the operation to complete - op, err = waitOpZone(config, op, d.Get("zone").(string), "InstanceGroupManager", "update TargetPools") + err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } d.SetPartial("target_pools") } @@ -233,13 +203,10 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte } // Wait for the operation to complete - op, err = waitOpZone(config, op, d.Get("zone").(string), "InstanceGroupManager", "update instance template") + err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } d.SetPartial("instance_template") } @@ -257,13 +224,10 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte } // Wait for the operation to complete - op, err = waitOpZone(config, op, d.Get("zone").(string), "InstanceGroupManager", "update target_size") + err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } } d.SetPartial("target_size") @@ -284,17 +248,10 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte } // Wait for the operation to complete - op, err = waitOpZone(config, op, d.Get("zone").(string), "InstanceGroupManager", "delete") + err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Deleting InstanceGroupManager") if err != nil { return err } - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) - } d.SetId("") return nil diff --git a/builtin/providers/google/resource_compute_instance_template.go b/builtin/providers/google/resource_compute_instance_template.go index 060f4bb39..ec85f1ba6 100644 --- a/builtin/providers/google/resource_compute_instance_template.go +++ b/builtin/providers/google/resource_compute_instance_template.go @@ -2,7 +2,6 @@ package google import ( "fmt" - "time" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" @@ -305,11 +304,9 @@ func buildNetworks(d *schema.ResourceData, meta interface{}) (error, []*compute. for i := 0; i < networksCount; i++ { prefix := fmt.Sprintf("network_interface.%d", i) - source := "global/networks/default" + source := "global/networks/" if v, ok := d.GetOk(prefix + ".network"); ok { - if v.(string) != "default" { - source = v.(string) - } + source += v.(string) } // Build the networkInterface @@ -401,28 +398,9 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac // Store the ID now d.SetId(instanceTemplate.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Delay = 10 * time.Second - state.Timeout = 10 * time.Minute - state.MinTimeout = 2 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Creating Instance Template") if err != nil { - return fmt.Errorf("Error waiting for instance template to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeInstanceTemplateRead(d, meta) @@ -467,25 +445,9 @@ func resourceComputeInstanceTemplateDelete(d *schema.ResourceData, meta interfac return fmt.Errorf("Error deleting instance template: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Delay = 5 * time.Second - state.Timeout = 5 * time.Minute - state.MinTimeout = 2 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Deleting Instance Template") if err != nil { - return fmt.Errorf("Error waiting for instance template to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_network.go b/builtin/providers/google/resource_compute_network.go index 5e581eff2..5a61f2ad6 100644 --- a/builtin/providers/google/resource_compute_network.go +++ b/builtin/providers/google/resource_compute_network.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" @@ -60,27 +59,9 @@ func resourceComputeNetworkCreate(d *schema.ResourceData, meta interface{}) erro // It probably maybe worked, so store the ID now d.SetId(network.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Creating Network") if err != nil { - return fmt.Errorf("Error waiting for network to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeNetworkRead(d, meta) @@ -118,24 +99,9 @@ func resourceComputeNetworkDelete(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error deleting network: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Deleting Network") if err != nil { - return fmt.Errorf("Error waiting for network to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_project_metadata.go b/builtin/providers/google/resource_compute_project_metadata.go index 3471d9110..83b6fb0df 100644 --- a/builtin/providers/google/resource_compute_project_metadata.go +++ b/builtin/providers/google/resource_compute_project_metadata.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" // "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" @@ -30,30 +29,6 @@ func resourceComputeProjectMetadata() *schema.Resource { } } -func resourceOperationWaitGlobal(config *Config, op *compute.Operation, activity string) error { - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() - if err != nil { - return fmt.Errorf("Error waiting for %s: %s", activity, err) - } - - op = opRaw.(*compute.Operation) - if op.Error != nil { - return OperationError(*op.Error) - } - - return nil -} - func resourceComputeProjectMetadataCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -92,7 +67,7 @@ func resourceComputeProjectMetadataCreate(d *schema.ResourceData, meta interface log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink) - return resourceOperationWaitGlobal(config, op, "SetCommonMetadata") + return computeOperationWaitGlobal(config, op, "SetCommonMetadata") } err := MetadataRetryWrapper(createMD) @@ -153,7 +128,7 @@ func resourceComputeProjectMetadataUpdate(d *schema.ResourceData, meta interface // Optimistic locking requires the fingerprint received to match // the fingerprint we send the server, if there is a mismatch then we // are working on old data, and must retry - return resourceOperationWaitGlobal(config, op, "SetCommonMetadata") + return computeOperationWaitGlobal(config, op, "SetCommonMetadata") } err := MetadataRetryWrapper(updateMD) @@ -186,7 +161,7 @@ func resourceComputeProjectMetadataDelete(d *schema.ResourceData, meta interface log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink) - err = resourceOperationWaitGlobal(config, op, "SetCommonMetadata") + err = computeOperationWaitGlobal(config, op, "SetCommonMetadata") if err != nil { return err } diff --git a/builtin/providers/google/resource_compute_route.go b/builtin/providers/google/resource_compute_route.go index 53176c871..82b43d358 100644 --- a/builtin/providers/google/resource_compute_route.go +++ b/builtin/providers/google/resource_compute_route.go @@ -3,7 +3,6 @@ package google import ( "fmt" "log" - "time" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" @@ -171,27 +170,9 @@ func resourceComputeRouteCreate(d *schema.ResourceData, meta interface{}) error // It probably maybe worked, so store the ID now d.SetId(route.Name) - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Creating Route") if err != nil { - return fmt.Errorf("Error waiting for route to create: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - - // Return the error - return OperationError(*op.Error) + return err } return resourceComputeRouteRead(d, meta) @@ -228,24 +209,9 @@ func resourceComputeRouteDelete(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error deleting route: %s", err) } - // Wait for the operation to complete - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitGlobal, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() + err = computeOperationWaitGlobal(config, op, "Deleting Route") if err != nil { - return fmt.Errorf("Error waiting for route to delete: %s", err) - } - op = opRaw.(*compute.Operation) - if op.Error != nil { - // Return the error - return OperationError(*op.Error) + return err } d.SetId("") diff --git a/builtin/providers/google/resource_compute_target_pool.go b/builtin/providers/google/resource_compute_target_pool.go index 83611e2bd..37af4a1e7 100644 --- a/builtin/providers/google/resource_compute_target_pool.go +++ b/builtin/providers/google/resource_compute_target_pool.go @@ -4,7 +4,6 @@ import ( "fmt" "log" "strings" - "time" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" @@ -79,26 +78,6 @@ func convertStringArr(ifaceArr []interface{}) []string { return arr } -func waitOp(config *Config, op *compute.Operation, - resource string, action string) (*compute.Operation, error) { - - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Region: config.Region, - Project: config.Project, - Type: OperationWaitRegion, - } - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() - if err != nil { - return nil, fmt.Errorf("Error waiting for %s to %s: %s", resource, action, err) - } - return opRaw.(*compute.Operation), nil -} - // Healthchecks need to exist before being referred to from the target pool. func convertHealthChecks(config *Config, names []string) ([]string, error) { urls := make([]string, len(names)) @@ -171,16 +150,10 @@ func resourceComputeTargetPoolCreate(d *schema.ResourceData, meta interface{}) e // It probably maybe worked, so store the ID now d.SetId(tpool.Name) - op, err = waitOp(config, op, "TargetPool", "create") + err = computeOperationWaitRegion(config, op, config.Region, "Creating Target Pool") if err != nil { return err } - if op.Error != nil { - // The resource didn't actually create - d.SetId("") - // Return the error - return OperationError(*op.Error) - } return resourceComputeTargetPoolRead(d, meta) } @@ -246,14 +219,11 @@ func resourceComputeTargetPoolUpdate(d *schema.ResourceData, meta interface{}) e if err != nil { return fmt.Errorf("Error updating health_check: %s", err) } - op, err = waitOp(config, op, "TargetPool", "removing HealthChecks") + + err = computeOperationWaitRegion(config, op, config.Region, "Updating Target Pool") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } - addReq := &compute.TargetPoolsAddHealthCheckRequest{ HealthChecks: make([]*compute.HealthCheckReference, len(add)), } @@ -265,14 +235,11 @@ func resourceComputeTargetPoolUpdate(d *schema.ResourceData, meta interface{}) e if err != nil { return fmt.Errorf("Error updating health_check: %s", err) } - op, err = waitOp(config, op, "TargetPool", "adding HealthChecks") + + err = computeOperationWaitRegion(config, op, config.Region, "Updating Target Pool") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } - d.SetPartial("health_checks") } @@ -302,14 +269,11 @@ func resourceComputeTargetPoolUpdate(d *schema.ResourceData, meta interface{}) e if err != nil { return fmt.Errorf("Error updating instances: %s", err) } - op, err = waitOp(config, op, "TargetPool", "adding instances") + + err = computeOperationWaitRegion(config, op, config.Region, "Updating Target Pool") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } - removeReq := &compute.TargetPoolsRemoveInstanceRequest{ Instances: make([]*compute.InstanceReference, len(remove)), } @@ -321,14 +285,11 @@ func resourceComputeTargetPoolUpdate(d *schema.ResourceData, meta interface{}) e if err != nil { return fmt.Errorf("Error updating instances: %s", err) } - op, err = waitOp(config, op, "TargetPool", "removing instances") + + err = computeOperationWaitRegion(config, op, config.Region, "Updating Target Pool") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } - d.SetPartial("instances") } @@ -343,14 +304,10 @@ func resourceComputeTargetPoolUpdate(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error updating backup_pool: %s", err) } - op, err = waitOp(config, op, "TargetPool", "updating backup_pool") + err = computeOperationWaitRegion(config, op, config.Region, "Updating Target Pool") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } - d.SetPartial("backup_pool") } @@ -390,14 +347,10 @@ func resourceComputeTargetPoolDelete(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error deleting TargetPool: %s", err) } - op, err = waitOp(config, op, "TargetPool", "delete") + err = computeOperationWaitRegion(config, op, config.Region, "Deleting Target Pool") if err != nil { return err } - if op.Error != nil { - return OperationError(*op.Error) - } - d.SetId("") return nil } diff --git a/builtin/providers/google/resource_compute_vpn_gateway.go b/builtin/providers/google/resource_compute_vpn_gateway.go index 01a6c4b94..ba25aeb1f 100644 --- a/builtin/providers/google/resource_compute_vpn_gateway.go +++ b/builtin/providers/google/resource_compute_vpn_gateway.go @@ -69,7 +69,7 @@ func resourceComputeVpnGatewayCreate(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error Inserting VPN Gateway %s into network %s: %s", name, network, err) } - err = resourceOperationWaitRegion(config, op, region, "Inserting VPN Gateway") + err = computeOperationWaitRegion(config, op, region, "Inserting VPN Gateway") if err != nil { return fmt.Errorf("Error Waiting to Insert VPN Gateway %s into network %s: %s", name, network, err) } @@ -111,7 +111,7 @@ func resourceComputeVpnGatewayDelete(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error Reading VPN Gateway %s: %s", name, err) } - err = resourceOperationWaitRegion(config, op, region, "Deleting VPN Gateway") + err = computeOperationWaitRegion(config, op, region, "Deleting VPN Gateway") if err != nil { return fmt.Errorf("Error Waiting to Delete VPN Gateway %s: %s", name, err) } diff --git a/builtin/providers/google/resource_compute_vpn_tunnel.go b/builtin/providers/google/resource_compute_vpn_tunnel.go index 55848d546..172f96a90 100644 --- a/builtin/providers/google/resource_compute_vpn_tunnel.go +++ b/builtin/providers/google/resource_compute_vpn_tunnel.go @@ -2,7 +2,6 @@ package google import ( "fmt" - "time" "github.com/hashicorp/terraform/helper/schema" @@ -66,31 +65,6 @@ func resourceComputeVpnTunnel() *schema.Resource { } } -func resourceOperationWaitRegion(config *Config, op *compute.Operation, region, activity string) error { - w := &OperationWaiter{ - Service: config.clientCompute, - Op: op, - Project: config.Project, - Type: OperationWaitRegion, - Region: region, - } - - state := w.Conf() - state.Timeout = 2 * time.Minute - state.MinTimeout = 1 * time.Second - opRaw, err := state.WaitForState() - if err != nil { - return fmt.Errorf("Error waiting for %s: %s", activity, err) - } - - op = opRaw.(*compute.Operation) - if op.Error != nil { - return OperationError(*op.Error) - } - - return nil -} - func resourceComputeVpnTunnelCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -125,7 +99,7 @@ func resourceComputeVpnTunnelCreate(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Error Inserting VPN Tunnel %s : %s", name, err) } - err = resourceOperationWaitRegion(config, op, region, "Inserting VPN Tunnel") + err = computeOperationWaitRegion(config, op, region, "Inserting VPN Tunnel") if err != nil { return fmt.Errorf("Error Waiting to Insert VPN Tunnel %s: %s", name, err) } @@ -169,7 +143,7 @@ func resourceComputeVpnTunnelDelete(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Error Reading VPN Tunnel %s: %s", name, err) } - err = resourceOperationWaitRegion(config, op, region, "Deleting VPN Tunnel") + err = computeOperationWaitRegion(config, op, region, "Deleting VPN Tunnel") if err != nil { return fmt.Errorf("Error Waiting to Delete VPN Tunnel %s: %s", name, err) } diff --git a/builtin/providers/openstack/resource_openstack_compute_instance_v2.go b/builtin/providers/openstack/resource_openstack_compute_instance_v2.go index f08f94031..75014cc75 100644 --- a/builtin/providers/openstack/resource_openstack_compute_instance_v2.go +++ b/builtin/providers/openstack/resource_openstack_compute_instance_v2.go @@ -610,13 +610,6 @@ func resourceComputeInstanceV2Update(d *schema.ResourceData, meta interface{}) e log.Printf("[DEBUG] Security groups to remove: %v", secgroupsToRemove) - for _, g := range secgroupsToAdd.List() { - err := secgroups.AddServerToGroup(computeClient, d.Id(), g.(string)).ExtractErr() - if err != nil { - return fmt.Errorf("Error adding security group to OpenStack server (%s): %s", d.Id(), err) - } - log.Printf("[DEBUG] Added security group (%s) to instance (%s)", g.(string), d.Id()) - } for _, g := range secgroupsToRemove.List() { err := secgroups.RemoveServerFromGroup(computeClient, d.Id(), g.(string)).ExtractErr() @@ -634,6 +627,14 @@ func resourceComputeInstanceV2Update(d *schema.ResourceData, meta interface{}) e log.Printf("[DEBUG] Removed security group (%s) from instance (%s)", g.(string), d.Id()) } } + for _, g := range secgroupsToAdd.List() { + err := secgroups.AddServerToGroup(computeClient, d.Id(), g.(string)).ExtractErr() + if err != nil { + return fmt.Errorf("Error adding security group to OpenStack server (%s): %s", d.Id(), err) + } + log.Printf("[DEBUG] Added security group (%s) to instance (%s)", g.(string), d.Id()) + } + } if d.HasChange("admin_pass") { diff --git a/builtin/provisioners/chef/linux_provisioner_test.go b/builtin/provisioners/chef/linux_provisioner_test.go index 27a1dbba0..6c57bfef0 100644 --- a/builtin/provisioners/chef/linux_provisioner_test.go +++ b/builtin/provisioners/chef/linux_provisioner_test.go @@ -310,6 +310,8 @@ validation_client_name "validator" node_name "nodename1" + + http_proxy "http://proxy.local" ENV['http_proxy'] = "http://proxy.local" ENV['HTTP_PROXY'] = "http://proxy.local" diff --git a/builtin/provisioners/chef/resource_provisioner.go b/builtin/provisioners/chef/resource_provisioner.go index f50b1b831..d7dbd718d 100644 --- a/builtin/provisioners/chef/resource_provisioner.go +++ b/builtin/provisioners/chef/resource_provisioner.go @@ -41,6 +41,12 @@ chef_server_url "{{ .ServerURL }}" validation_client_name "{{ .ValidationClientName }}" node_name "{{ .NodeName }}" +{{ if .UsePolicyfile }} +use_policyfile true +policy_group "{{ .PolicyGroup }}" +policy_name "{{ .PolicyName }}" +{{ end }} + {{ if .HTTPProxy }} http_proxy "{{ .HTTPProxy }}" ENV['http_proxy'] = "{{ .HTTPProxy }}" @@ -62,6 +68,9 @@ type Provisioner struct { Attributes interface{} `mapstructure:"attributes"` Environment string `mapstructure:"environment"` LogToFile bool `mapstructure:"log_to_file"` + UsePolicyfile bool `mapstructure:"use_policyfile"` + PolicyGroup string `mapstructure:"policy_group"` + PolicyName string `mapstructure:"policy_name"` HTTPProxy string `mapstructure:"http_proxy"` HTTPSProxy string `mapstructure:"https_proxy"` NOProxy []string `mapstructure:"no_proxy"` @@ -183,6 +192,12 @@ func (r *ResourceProvisioner) Validate(c *terraform.ResourceConfig) (ws []string if p.ValidationKeyPath == "" { es = append(es, fmt.Errorf("Key not found: validation_key_path")) } + if p.UsePolicyfile && p.PolicyName == "" { + es = append(es, fmt.Errorf("Policyfile enabled but key not found: policy_name")) + } + if p.UsePolicyfile && p.PolicyGroup == "" { + es = append(es, fmt.Errorf("Policyfile enabled but key not found: policy_group")) + } return ws, es } @@ -302,7 +317,15 @@ func (p *Provisioner) runChefClientFunc( confDir string) func(terraform.UIOutput, communicator.Communicator) error { return func(o terraform.UIOutput, comm communicator.Communicator) error { fb := path.Join(confDir, firstBoot) - cmd := fmt.Sprintf("%s -j %q -E %q", chefCmd, fb, p.Environment) + var cmd string + + // Policyfiles do not support chef environments, so don't pass the `-E` flag. + if p.UsePolicyfile { + cmd = fmt.Sprintf("%s -j %q", chefCmd, fb) + } else { + cmd = fmt.Sprintf("%s -j %q -E %q", chefCmd, fb, p.Environment) + } + if p.LogToFile { if err := os.MkdirAll(logfileDir, 0755); err != nil { @@ -413,7 +436,9 @@ func (p *Provisioner) deployConfigFiles( } // Add the initial runlist to the first boot settings - fb["run_list"] = p.RunList + if !p.UsePolicyfile { + fb["run_list"] = p.RunList + } // Marshal the first boot settings to JSON d, err := json.Marshal(fb) diff --git a/builtin/provisioners/chef/windows_provisioner_test.go b/builtin/provisioners/chef/windows_provisioner_test.go index a01599a30..11e61d888 100644 --- a/builtin/provisioners/chef/windows_provisioner_test.go +++ b/builtin/provisioners/chef/windows_provisioner_test.go @@ -342,6 +342,8 @@ validation_client_name "validator" node_name "nodename1" + + http_proxy "http://proxy.local" ENV['http_proxy'] = "http://proxy.local" ENV['HTTP_PROXY'] = "http://proxy.local" diff --git a/terraform/context_input_test.go b/terraform/context_input_test.go index 155f4c72f..404ef0ffc 100644 --- a/terraform/context_input_test.go +++ b/terraform/context_input_test.go @@ -510,3 +510,62 @@ aws_instance.foo: t.Fatalf("expected: \n%s\ngot: \n%s\n", expectedStr, actualStr) } } + +func TestContext2Input_varPartiallyComputed(t *testing.T) { + input := new(MockUIInput) + m := testModule(t, "input-var-partially-computed") + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + Variables: map[string]string{ + "foo": "foovalue", + }, + UIInput: input, + State: &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_instance.foo": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "i-abc123", + Attributes: map[string]string{ + "id": "i-abc123", + }, + }, + }, + }, + }, + &ModuleState{ + Path: append(rootModulePath, "child"), + Resources: map[string]*ResourceState{ + "aws_instance.mod": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "i-bcd345", + Attributes: map[string]string{ + "id": "i-bcd345", + "value": "one,i-abc123", + }, + }, + }, + }, + }, + }, + }, + }) + + if err := ctx.Input(InputModeStd); err != nil { + t.Fatalf("err: %s", err) + } + + if _, err := ctx.Plan(); err != nil { + t.Fatalf("err: %s", err) + } +} diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 15b81cdbd..d8e5288ec 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -378,7 +378,13 @@ MISSING: // be unknown. Instead, we return that the value is computed so // that the graph can continue to refresh other nodes. It doesn't // matter because the config isn't interpolated anyways. - if i.Operation == walkRefresh || i.Operation == walkPlanDestroy { + // + // For a Destroy, we're also fine with computed values, since our goal is + // only to get destroy nodes for existing resources. + // + // For an input walk, computed values are okay to return because we're only + // looking for missing variables to prompt the user for. + if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkInput { return config.UnknownVariableValue, nil } @@ -469,7 +475,13 @@ func (i *Interpolater) computeResourceMultiVariable( // be unknown. Instead, we return that the value is computed so // that the graph can continue to refresh other nodes. It doesn't // matter because the config isn't interpolated anyways. - if i.Operation == walkRefresh || i.Operation == walkPlanDestroy { + // + // For a Destroy, we're also fine with computed values, since our goal is + // only to get destroy nodes for existing resources. + // + // For an input walk, computed values are okay to return because we're only + // looking for missing variables to prompt the user for. + if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkInput { return config.UnknownVariableValue, nil } diff --git a/terraform/test-fixtures/input-var-partially-computed/child/main.tf b/terraform/test-fixtures/input-var-partially-computed/child/main.tf new file mode 100644 index 000000000..a11cc5e83 --- /dev/null +++ b/terraform/test-fixtures/input-var-partially-computed/child/main.tf @@ -0,0 +1,5 @@ +variable "in" {} + +resource "aws_instance" "mod" { + value = "${var.in}" +} diff --git a/terraform/test-fixtures/input-var-partially-computed/main.tf b/terraform/test-fixtures/input-var-partially-computed/main.tf new file mode 100644 index 000000000..ada6f0cea --- /dev/null +++ b/terraform/test-fixtures/input-var-partially-computed/main.tf @@ -0,0 +1,7 @@ +resource "aws_instance" "foo" { } +resource "aws_instance" "bar" { } + +module "child" { + source = "./child" + in = "one,${aws_instance.foo.id},${aws_instance.bar.id}" +} diff --git a/website/Gemfile.lock b/website/Gemfile.lock index 826d25e8f..fac790740 100644 --- a/website/Gemfile.lock +++ b/website/Gemfile.lock @@ -1,12 +1,12 @@ GIT remote: https://github.com/hashicorp/middleman-hashicorp - revision: 76f0f284ad44cea0457484ea83467192f02daf87 + revision: fc131cfce2a1d5c8671812d9844a944ebb4bd92f specs: middleman-hashicorp (0.1.0) bootstrap-sass (~> 3.3) builder (~> 3.2) less (~> 2.6) - middleman (~> 3.3) + middleman (~> 3.4) middleman-livereload (~> 3.4) middleman-minify-html (~> 3.4) middleman-syntax (~> 2.0) @@ -21,21 +21,25 @@ GIT GEM remote: https://rubygems.org/ specs: - activesupport (4.1.12) - i18n (~> 0.6, >= 0.6.9) + activesupport (4.2.4) + i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) - thread_safe (~> 0.1) + thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - autoprefixer-rails (5.2.1) + autoprefixer-rails (6.0.3) execjs json bootstrap-sass (3.3.5.1) autoprefixer-rails (>= 5.0.0.1) sass (>= 3.3.0) builder (3.2.2) - celluloid (0.16.0) - timers (~> 4.0.0) + capybara (2.4.4) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) chunky_png (1.3.4) coffee-script (2.4.1) coffee-script-source @@ -59,16 +63,15 @@ GEM eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) erubis (2.7.0) - eventmachine (1.0.7) - execjs (2.5.2) + eventmachine (1.0.8) + execjs (2.6.0) ffi (1.9.10) git-version-bump (0.15.1) - haml (4.0.6) + haml (4.0.7) tilt hike (1.2.3) - hitimes (1.2.2) - hooks (0.4.0) - uber (~> 0.0.4) + hooks (0.4.1) + uber (~> 0.0.14) htmlcompressor (0.2.0) http_parser.rb (0.6.0) i18n (0.7.0) @@ -77,34 +80,33 @@ GEM less (2.6.0) commonjs (~> 0.2.7) libv8 (3.16.14.11) - listen (2.10.1) - celluloid (~> 0.16.0) + listen (3.0.3) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) - middleman (3.3.12) + middleman (3.4.0) coffee-script (~> 2.2) compass (>= 1.0.0, < 2.0.0) compass-import-once (= 1.0.5) execjs (~> 2.0) haml (>= 4.0.5) kramdown (~> 1.2) - middleman-core (= 3.3.12) + middleman-core (= 3.4.0) middleman-sprockets (>= 3.1.2) sass (>= 3.4.0, < 4.0) uglifier (~> 2.5) - middleman-core (3.3.12) - activesupport (~> 4.1.0) + middleman-core (3.4.0) + activesupport (~> 4.1) bundler (~> 1.1) + capybara (~> 2.4.4) erubis hooks (~> 0.3) i18n (~> 0.7.0) - listen (>= 2.7.9, < 3.0) + listen (~> 3.0.3) padrino-helpers (~> 0.12.3) rack (>= 1.4.5, < 2.0) - rack-test (~> 0.6.2) thor (>= 0.15.2, < 2.0) tilt (~> 1.4.1, < 2.0) - middleman-livereload (3.4.2) + middleman-livereload (3.4.3) em-websocket (~> 0.5.1) middleman-core (>= 3.3) rack-livereload (~> 0.3.15) @@ -119,8 +121,12 @@ GEM middleman-syntax (2.0.0) middleman-core (~> 3.2) rouge (~> 1.0) - minitest (5.7.0) + mime-types (2.6.2) + mini_portile (0.6.2) + minitest (5.8.1) multi_json (1.11.2) + nokogiri (1.6.6.2) + mini_portile (~> 0.6.0) padrino-helpers (0.12.5) i18n (~> 0.6, >= 0.6.7) padrino-support (= 0.12.5) @@ -128,7 +134,7 @@ GEM padrino-support (0.12.5) activesupport (>= 3.1) rack (1.6.4) - rack-contrib (1.3.0) + rack-contrib (1.4.0) git-version-bump (~> 0.15) rack (~> 1.4) rack-livereload (0.3.16) @@ -136,16 +142,16 @@ GEM rack-protection (1.5.3) rack rack-rewrite (1.5.1) - rack-ssl-enforcer (0.2.8) + rack-ssl-enforcer (0.2.9) rack-test (0.6.3) rack (>= 1.0) - rb-fsevent (0.9.5) + rb-fsevent (0.9.6) rb-inotify (0.9.5) ffi (>= 0.5.0) redcarpet (3.3.2) ref (2.0.0) - rouge (1.9.1) - sass (3.4.16) + rouge (1.10.1) + sass (3.4.18) sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) @@ -159,24 +165,27 @@ GEM therubyracer (0.12.2) libv8 (~> 3.16.14.0) ref - thin (1.6.3) + thin (1.6.4) daemons (~> 1.0, >= 1.0.9) - eventmachine (~> 1.0) + eventmachine (~> 1.0, >= 1.0.4) rack (~> 1.0) thor (0.19.1) thread_safe (0.3.5) tilt (1.4.1) - timers (4.0.1) - hitimes tzinfo (1.2.2) thread_safe (~> 0.1) - uber (0.0.13) - uglifier (2.7.1) + uber (0.0.15) + uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) + xpath (2.0.0) + nokogiri (~> 1.3) PLATFORMS ruby DEPENDENCIES middleman-hashicorp! + +BUNDLED WITH + 1.10.6 diff --git a/website/Makefile b/website/Makefile new file mode 100644 index 000000000..63bb4cab1 --- /dev/null +++ b/website/Makefile @@ -0,0 +1,10 @@ +all: build + +init: + bundle + +dev: init + bundle exec middleman server + +build: init + bundle exec middleman build \ No newline at end of file diff --git a/website/README.md b/website/README.md index 0e1c0fa49..cb83f714d 100644 --- a/website/README.md +++ b/website/README.md @@ -12,15 +12,7 @@ requests like any normal GitHub project, and we'll merge it in. ## Running the Site Locally -Running the site locally is simple. First you need a working copy of [Ruby >= 2.0](https://www.ruby-lang.org/en/downloads/) and [Bundler](http://bundler.io/). -Then you can clone this repo and run the following commands from this directory: - -``` -$ bundle -# ( installs all gem dependencies ) -$ bundle exec middleman server -# ( boots the local server ) -``` +Running the site locally is simple. First you need a working copy of [Ruby >= 2.0](https://www.ruby-lang.org/en/downloads/) and [Bundler](http://bundler.io/). Then you can clone this repo and run `make dev`. Then open up `http://localhost:4567`. Note that some URLs you may need to append ".html" to make them work (in the navigation). diff --git a/website/source/docs/providers/aws/r/vpc_endpoint.html.markdown b/website/source/docs/providers/aws/r/vpc_endpoint.html.markdown index 813aba329..51fdbf5ee 100644 --- a/website/source/docs/providers/aws/r/vpc_endpoint.html.markdown +++ b/website/source/docs/providers/aws/r/vpc_endpoint.html.markdown @@ -27,7 +27,7 @@ The following arguments are supported: * `vpc_id` - (Required) The ID of the VPC in which the endpoint will be used. * `service_name` - (Required) The AWS service name, in the form `com.amazonaws.region.service`. -* `policy_document` - (Optional) A policy to attach to the endpoint that controls access to the service. +* `policy` - (Optional) A policy to attach to the endpoint that controls access to the service. * `route_table_ids` - (Optional) One or more route table IDs. ## Attributes Reference diff --git a/website/source/docs/providers/rundeck/index.html.markdown b/website/source/docs/providers/rundeck/index.html.markdown index e948ca4e3..529f4f44b 100644 --- a/website/source/docs/providers/rundeck/index.html.markdown +++ b/website/source/docs/providers/rundeck/index.html.markdown @@ -70,6 +70,6 @@ resource "rundeck_public_key" "anvils" { resource "rundeck_private_key" "anvils" { path = "anvils/id_rsa" - key_material_file = "${path.module}/id_rsa.pub" + key_material = "${file(\"id_rsa.pub\")}" } ``` diff --git a/website/source/docs/providers/rundeck/r/private_key.html.md b/website/source/docs/providers/rundeck/r/private_key.html.md index 1850f588e..3d74aaf1d 100644 --- a/website/source/docs/providers/rundeck/r/private_key.html.md +++ b/website/source/docs/providers/rundeck/r/private_key.html.md @@ -17,7 +17,7 @@ it runs commands. ``` resource "rundeck_private_key" "anvils" { path = "anvils/id_rsa" - key_material = "${file(\"/id_rsa\")}" + key_material = "${file("/id_rsa")}" } ``` diff --git a/website/source/layouts/_footer.erb b/website/source/layouts/_footer.erb index df095a820..791861e42 100644 --- a/website/source/layouts/_footer.erb +++ b/website/source/layouts/_footer.erb @@ -6,7 +6,10 @@