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