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 }