github.com/armen/terraform@v0.5.2-0.20150529052519-caa8117a08f1/builtin/providers/aws/resource_aws_ebs_volume.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/awslabs/aws-sdk-go/aws" 9 "github.com/awslabs/aws-sdk-go/aws/awserr" 10 "github.com/awslabs/aws-sdk-go/service/ec2" 11 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 func resourceAwsEbsVolume() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceAwsEbsVolumeCreate, 19 Read: resourceAwsEbsVolumeRead, 20 Delete: resourceAwsEbsVolumeDelete, 21 22 Schema: map[string]*schema.Schema{ 23 "availability_zone": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 }, 28 "encrypted": &schema.Schema{ 29 Type: schema.TypeBool, 30 Optional: true, 31 Computed: true, 32 ForceNew: true, 33 }, 34 "iops": &schema.Schema{ 35 Type: schema.TypeInt, 36 Optional: true, 37 Computed: true, 38 ForceNew: true, 39 }, 40 "kms_key_id": &schema.Schema{ 41 Type: schema.TypeString, 42 Optional: true, 43 Computed: true, 44 ForceNew: true, 45 }, 46 "size": &schema.Schema{ 47 Type: schema.TypeInt, 48 Optional: true, 49 Computed: true, 50 ForceNew: true, 51 }, 52 "snapshot_id": &schema.Schema{ 53 Type: schema.TypeString, 54 Optional: true, 55 Computed: true, 56 ForceNew: true, 57 }, 58 "type": &schema.Schema{ 59 Type: schema.TypeString, 60 Optional: true, 61 Computed: true, 62 ForceNew: true, 63 }, 64 }, 65 } 66 } 67 68 func resourceAwsEbsVolumeCreate(d *schema.ResourceData, meta interface{}) error { 69 conn := meta.(*AWSClient).ec2conn 70 71 request := &ec2.CreateVolumeInput{ 72 AvailabilityZone: aws.String(d.Get("availability_zone").(string)), 73 } 74 if value, ok := d.GetOk("encrypted"); ok { 75 request.Encrypted = aws.Boolean(value.(bool)) 76 } 77 if value, ok := d.GetOk("iops"); ok { 78 request.IOPS = aws.Long(int64(value.(int))) 79 } 80 if value, ok := d.GetOk("kms_key_id"); ok { 81 request.KMSKeyID = aws.String(value.(string)) 82 } 83 if value, ok := d.GetOk("size"); ok { 84 request.Size = aws.Long(int64(value.(int))) 85 } 86 if value, ok := d.GetOk("snapshot_id"); ok { 87 request.SnapshotID = aws.String(value.(string)) 88 } 89 if value, ok := d.GetOk("type"); ok { 90 request.VolumeType = aws.String(value.(string)) 91 } 92 93 result, err := conn.CreateVolume(request) 94 if err != nil { 95 return fmt.Errorf("Error creating EC2 volume: %s", err) 96 } 97 98 log.Printf( 99 "[DEBUG] Waiting for Volume (%s) to become available", 100 d.Id()) 101 102 stateConf := &resource.StateChangeConf{ 103 Pending: []string{"creating"}, 104 Target: "available", 105 Refresh: volumeStateRefreshFunc(conn, *result.VolumeID), 106 Timeout: 5 * time.Minute, 107 Delay: 10 * time.Second, 108 MinTimeout: 3 * time.Second, 109 } 110 111 _, err = stateConf.WaitForState() 112 if err != nil { 113 return fmt.Errorf( 114 "Error waiting for Volume (%s) to become available: %s", 115 *result.VolumeID, err) 116 } 117 118 return readVolume(d, result) 119 } 120 121 // volumeStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch 122 // a the state of a Volume. Returns successfully when volume is available 123 func volumeStateRefreshFunc(conn *ec2.EC2, volumeID string) resource.StateRefreshFunc { 124 return func() (interface{}, string, error) { 125 resp, err := conn.DescribeVolumes(&ec2.DescribeVolumesInput{ 126 VolumeIDs: []*string{aws.String(volumeID)}, 127 }) 128 129 if err != nil { 130 if ec2err, ok := err.(awserr.Error); ok { 131 // Set this to nil as if we didn't find anything. 132 log.Printf("Error on Volume State Refresh: message: \"%s\", code:\"%s\"", ec2err.Message(), ec2err.Code()) 133 resp = nil 134 return nil, "", err 135 } else { 136 log.Printf("Error on Volume State Refresh: %s", err) 137 return nil, "", err 138 } 139 } 140 141 v := resp.Volumes[0] 142 return v, *v.State, nil 143 } 144 } 145 146 func resourceAwsEbsVolumeRead(d *schema.ResourceData, meta interface{}) error { 147 conn := meta.(*AWSClient).ec2conn 148 149 request := &ec2.DescribeVolumesInput{ 150 VolumeIDs: []*string{aws.String(d.Id())}, 151 } 152 153 response, err := conn.DescribeVolumes(request) 154 if err != nil { 155 if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVolume.NotFound" { 156 d.SetId("") 157 return nil 158 } 159 return fmt.Errorf("Error reading EC2 volume %s: %#v", d.Id(), err) 160 } 161 162 return readVolume(d, response.Volumes[0]) 163 } 164 165 func resourceAwsEbsVolumeDelete(d *schema.ResourceData, meta interface{}) error { 166 conn := meta.(*AWSClient).ec2conn 167 168 request := &ec2.DeleteVolumeInput{ 169 VolumeID: aws.String(d.Id()), 170 } 171 172 _, err := conn.DeleteVolume(request) 173 if err != nil { 174 return fmt.Errorf("Error deleting EC2 volume %s: %s", d.Id(), err) 175 } 176 return nil 177 } 178 179 func readVolume(d *schema.ResourceData, volume *ec2.Volume) error { 180 d.SetId(*volume.VolumeID) 181 182 d.Set("availability_zone", *volume.AvailabilityZone) 183 if volume.Encrypted != nil { 184 d.Set("encrypted", *volume.Encrypted) 185 } 186 if volume.IOPS != nil { 187 d.Set("iops", *volume.IOPS) 188 } 189 if volume.KMSKeyID != nil { 190 d.Set("kms_key_id", *volume.KMSKeyID) 191 } 192 if volume.Size != nil { 193 d.Set("size", *volume.Size) 194 } 195 if volume.SnapshotID != nil { 196 d.Set("snapshot_id", *volume.SnapshotID) 197 } 198 if volume.VolumeType != nil { 199 d.Set("type", *volume.VolumeType) 200 } 201 202 return nil 203 }