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  }