github.com/emc-cmd/terraform@v0.7.8-0.20161101145618-f16309630e7c/builtin/providers/aws/data_source_aws_ebs_volume.go (about)

     1  package aws
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"sort"
     8  
     9  	"github.com/aws/aws-sdk-go/aws"
    10  	"github.com/aws/aws-sdk-go/service/ec2"
    11  	"github.com/davecgh/go-spew/spew"
    12  	"github.com/hashicorp/terraform/helper/hashcode"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  )
    15  
    16  func dataSourceAwsEbsVolume() *schema.Resource {
    17  	return &schema.Resource{
    18  		Read: dataSourceAwsEbsVolumeRead,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"filter": {
    22  				Type:     schema.TypeSet,
    23  				Optional: true,
    24  				ForceNew: true,
    25  				Elem: &schema.Resource{
    26  					Schema: map[string]*schema.Schema{
    27  						"name": {
    28  							Type:     schema.TypeString,
    29  							Required: true,
    30  						},
    31  
    32  						"values": {
    33  							Type:     schema.TypeList,
    34  							Required: true,
    35  							Elem:     &schema.Schema{Type: schema.TypeString},
    36  						},
    37  					},
    38  				},
    39  			},
    40  			"most_recent": {
    41  				Type:     schema.TypeBool,
    42  				Optional: true,
    43  				Default:  false,
    44  				ForceNew: true,
    45  			},
    46  			"availability_zone": {
    47  				Type:     schema.TypeString,
    48  				Computed: true,
    49  			},
    50  			"encrypted": {
    51  				Type:     schema.TypeBool,
    52  				Computed: true,
    53  			},
    54  			"iops": {
    55  				Type:     schema.TypeInt,
    56  				Computed: true,
    57  			},
    58  			"volume_type": {
    59  				Type:     schema.TypeString,
    60  				Computed: true,
    61  			},
    62  			"size": {
    63  				Type:     schema.TypeInt,
    64  				Computed: true,
    65  			},
    66  			"snapshot_id": {
    67  				Type:     schema.TypeString,
    68  				Computed: true,
    69  			},
    70  			"kms_key_id": {
    71  				Type:     schema.TypeString,
    72  				Computed: true,
    73  			},
    74  			"volume_id": {
    75  				Type:     schema.TypeString,
    76  				Computed: true,
    77  			},
    78  			"tags": {
    79  				Type:     schema.TypeSet,
    80  				Computed: true,
    81  				Set:      volumeTagsHash,
    82  				Elem: &schema.Resource{
    83  					Schema: map[string]*schema.Schema{
    84  						"key": {
    85  							Type:     schema.TypeString,
    86  							Computed: true,
    87  						},
    88  						"value": {
    89  							Type:     schema.TypeString,
    90  							Computed: true,
    91  						},
    92  					},
    93  				},
    94  			},
    95  		},
    96  	}
    97  }
    98  
    99  func dataSourceAwsEbsVolumeRead(d *schema.ResourceData, meta interface{}) error {
   100  	conn := meta.(*AWSClient).ec2conn
   101  
   102  	filters, filtersOk := d.GetOk("filter")
   103  
   104  	params := &ec2.DescribeVolumesInput{}
   105  	if filtersOk {
   106  		params.Filters = buildVolumeFilters(filters.(*schema.Set))
   107  	}
   108  
   109  	resp, err := conn.DescribeVolumes(params)
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	log.Printf("Found These Volumes %s", spew.Sdump(resp.Volumes))
   115  
   116  	filteredVolumes := resp.Volumes[:]
   117  
   118  	var volume *ec2.Volume
   119  	if len(filteredVolumes) < 1 {
   120  		return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
   121  	}
   122  
   123  	if len(filteredVolumes) > 1 {
   124  		recent := d.Get("most_recent").(bool)
   125  		log.Printf("[DEBUG] aws_ebs_volume - multiple results found and `most_recent` is set to: %t", recent)
   126  		if recent {
   127  			volume = mostRecentVolume(filteredVolumes)
   128  		} else {
   129  			return fmt.Errorf("Your query returned more than one result. Please try a more " +
   130  				"specific search criteria, or set `most_recent` attribute to true.")
   131  		}
   132  	} else {
   133  		// Query returned single result.
   134  		volume = filteredVolumes[0]
   135  	}
   136  
   137  	log.Printf("[DEBUG] aws_ebs_volume - Single Volume found: %s", *volume.VolumeId)
   138  	return volumeDescriptionAttributes(d, volume)
   139  }
   140  
   141  func buildVolumeFilters(set *schema.Set) []*ec2.Filter {
   142  	var filters []*ec2.Filter
   143  	for _, v := range set.List() {
   144  		m := v.(map[string]interface{})
   145  		var filterValues []*string
   146  		for _, e := range m["values"].([]interface{}) {
   147  			filterValues = append(filterValues, aws.String(e.(string)))
   148  		}
   149  		filters = append(filters, &ec2.Filter{
   150  			Name:   aws.String(m["name"].(string)),
   151  			Values: filterValues,
   152  		})
   153  	}
   154  	return filters
   155  }
   156  
   157  type volumeSort []*ec2.Volume
   158  
   159  func (a volumeSort) Len() int      { return len(a) }
   160  func (a volumeSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
   161  func (a volumeSort) Less(i, j int) bool {
   162  	itime := *a[i].CreateTime
   163  	jtime := *a[j].CreateTime
   164  	return itime.Unix() < jtime.Unix()
   165  }
   166  
   167  func mostRecentVolume(volumes []*ec2.Volume) *ec2.Volume {
   168  	sortedVolumes := volumes
   169  	sort.Sort(volumeSort(sortedVolumes))
   170  	return sortedVolumes[len(sortedVolumes)-1]
   171  }
   172  
   173  func volumeDescriptionAttributes(d *schema.ResourceData, volume *ec2.Volume) error {
   174  	d.SetId(*volume.VolumeId)
   175  	d.Set("volume_id", volume.VolumeId)
   176  	d.Set("availability_zone", volume.AvailabilityZone)
   177  	d.Set("encrypted", volume.Encrypted)
   178  	d.Set("iops", volume.Iops)
   179  	d.Set("kms_key_id", volume.KmsKeyId)
   180  	d.Set("size", volume.Size)
   181  	d.Set("snapshot_id", volume.SnapshotId)
   182  	d.Set("volume_type", volume.VolumeType)
   183  
   184  	if err := d.Set("tags", volumeTags(volume.Tags)); err != nil {
   185  		return err
   186  	}
   187  
   188  	return nil
   189  }
   190  
   191  func volumeTags(m []*ec2.Tag) *schema.Set {
   192  	s := &schema.Set{
   193  		F: volumeTagsHash,
   194  	}
   195  	for _, v := range m {
   196  		tag := map[string]interface{}{
   197  			"key":   *v.Key,
   198  			"value": *v.Value,
   199  		}
   200  		s.Add(tag)
   201  	}
   202  	return s
   203  }
   204  
   205  func volumeTagsHash(v interface{}) int {
   206  	var buf bytes.Buffer
   207  	m := v.(map[string]interface{})
   208  	buf.WriteString(fmt.Sprintf("%s-", m["key"].(string)))
   209  	buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
   210  	return hashcode.String(buf.String())
   211  }