From f10e84aa16643cec2b3d34bf7e8fa594fe95fcf6 Mon Sep 17 00:00:00 2001 From: Eric Buth Date: Fri, 17 Oct 2014 12:12:45 -0400 Subject: [PATCH] added block_device attribute --- .../providers/aws/resource_aws_instance.go | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index c1f9261fb..87f31d695 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -1,6 +1,7 @@ package aws import ( + "bytes" "crypto/sha1" "encoding/hex" "fmt" @@ -125,6 +126,52 @@ func resourceAwsInstance() *schema.Resource { Optional: true, }, "tags": tagsSchema(), + + "block_device": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "device_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "snapshot_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "volume_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "volume_size": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + + "delete_on_termination": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: true, + ForceNew: true, + }, + + "encrypted": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, + }, + }, + Set: resourceAwsInstanceBlockDevicesHash, + }, }, } } @@ -173,6 +220,22 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { } } + if v := d.Get("block_device"); v != nil { + vs := v.(*schema.Set).List() + if len(vs) > 0 { + runOpts.BlockDevices = make([]ec2.BlockDeviceMapping, len(vs)) + for i, v := range vs { + bd := v.(map[string]interface{}) + runOpts.BlockDevices[i].DeviceName = bd["device_name"].(string) + runOpts.BlockDevices[i].SnapshotId = bd["snapshot_id"].(string) + runOpts.BlockDevices[i].VolumeType = bd["volume_type"].(string) + runOpts.BlockDevices[i].VolumeSize = int64(bd["volume_size"].(int)) + runOpts.BlockDevices[i].DeleteOnTermination = bd["delete_on_termination"].(bool) + runOpts.BlockDevices[i].Encrypted = bd["encrypted"].(bool) + } + } + } + // Create the instance log.Printf("[DEBUG] Run configuration: %#v", runOpts) runResp, err := ec2conn.RunInstances(runOpts) @@ -360,6 +423,30 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { } d.Set("security_groups", sgs) + volIDs := make([]string, len(instance.BlockDevices)) + bdByVolID := make(map[string]ec2.BlockDevice) + for i, bd := range instance.BlockDevices { + volIDs[i] = bd.VolumeId + bdByVolID[bd.VolumeId] = bd + } + + volResp, err := ec2conn.Volumes(volIDs, ec2.NewFilter()) + if err != nil { + return err + } + + bds := make([]map[string]interface{}, len(instance.BlockDevices)) + for i, vol := range volResp.Volumes { + bds[i] = make(map[string]interface{}) + bds[i]["device_name"] = bdByVolID[vol.VolumeId].DeviceName + bds[i]["snapshot_id"] = vol.SnapshotId + bds[i]["volume_type"] = vol.VolumeType + bds[i]["volume_size"] = vol.Size + bds[i]["delete_on_termination"] = bdByVolID[vol.VolumeId].DeleteOnTermination + bds[i]["encrypted"] = vol.Encrypted + } + d.Set("block_device", bds) + return nil } @@ -388,3 +475,15 @@ func InstanceStateRefreshFunc(conn *ec2.EC2, instanceID string) resource.StateRe return i, i.State.Name, nil } } + +func resourceAwsInstanceBlockDevicesHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["device_name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["snapshot_id"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["volume_type"].(string))) + buf.WriteString(fmt.Sprintf("%d-", m["volume_size"].(int))) + buf.WriteString(fmt.Sprintf("%t-", m["delete_on_termination"].(bool))) + buf.WriteString(fmt.Sprintf("%t-", m["encrypted"].(bool))) + return hashcode.String(buf.String()) +}