forked from hashicorp/terraform
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
provider/aws: Adding a datasource for aws_ebs_volume (hashicorp#9753)
This will allows us to filter a specific ebs_volume for attachment to an aws_instance ``` make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSEbsVolumeDataSource_'✹ ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2016/11/01 12:39:19 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSEbsVolumeDataSource_ -timeout 120m === RUN TestAccAWSEbsVolumeDataSource_basic --- PASS: TestAccAWSEbsVolumeDataSource_basic (28.74s) === RUN TestAccAWSEbsVolumeDataSource_multipleFilters --- PASS: TestAccAWSEbsVolumeDataSource_multipleFilters (28.37s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws57.145s ```
- Loading branch information
Showing
5 changed files
with
377 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
package aws | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"sort" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ec2" | ||
"github.com/davecgh/go-spew/spew" | ||
"github.com/hashicorp/terraform/helper/hashcode" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func dataSourceAwsEbsVolume() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceAwsEbsVolumeRead, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"filter": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
ForceNew: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
|
||
"values": { | ||
Type: schema.TypeList, | ||
Required: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"most_recent": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
ForceNew: true, | ||
}, | ||
"availability_zone": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"encrypted": { | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
}, | ||
"iops": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
"volume_type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"size": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
"snapshot_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"kms_key_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"volume_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"tags": { | ||
Type: schema.TypeSet, | ||
Computed: true, | ||
Set: volumeTagsHash, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"key": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"value": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceAwsEbsVolumeRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
filters, filtersOk := d.GetOk("filter") | ||
|
||
params := &ec2.DescribeVolumesInput{} | ||
if filtersOk { | ||
params.Filters = buildVolumeFilters(filters.(*schema.Set)) | ||
} | ||
|
||
resp, err := conn.DescribeVolumes(params) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
log.Printf("Found These Volumes %s", spew.Sdump(resp.Volumes)) | ||
|
||
filteredVolumes := resp.Volumes[:] | ||
|
||
var volume *ec2.Volume | ||
if len(filteredVolumes) < 1 { | ||
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.") | ||
} | ||
|
||
if len(filteredVolumes) > 1 { | ||
recent := d.Get("most_recent").(bool) | ||
log.Printf("[DEBUG] aws_ebs_volume - multiple results found and `most_recent` is set to: %t", recent) | ||
if recent { | ||
volume = mostRecentVolume(filteredVolumes) | ||
} else { | ||
return fmt.Errorf("Your query returned more than one result. Please try a more " + | ||
"specific search criteria, or set `most_recent` attribute to true.") | ||
} | ||
} else { | ||
// Query returned single result. | ||
volume = filteredVolumes[0] | ||
} | ||
|
||
log.Printf("[DEBUG] aws_ebs_volume - Single Volume found: %s", *volume.VolumeId) | ||
return volumeDescriptionAttributes(d, volume) | ||
} | ||
|
||
func buildVolumeFilters(set *schema.Set) []*ec2.Filter { | ||
var filters []*ec2.Filter | ||
for _, v := range set.List() { | ||
m := v.(map[string]interface{}) | ||
var filterValues []*string | ||
for _, e := range m["values"].([]interface{}) { | ||
filterValues = append(filterValues, aws.String(e.(string))) | ||
} | ||
filters = append(filters, &ec2.Filter{ | ||
Name: aws.String(m["name"].(string)), | ||
Values: filterValues, | ||
}) | ||
} | ||
return filters | ||
} | ||
|
||
type volumeSort []*ec2.Volume | ||
|
||
func (a volumeSort) Len() int { return len(a) } | ||
func (a volumeSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } | ||
func (a volumeSort) Less(i, j int) bool { | ||
itime := *a[i].CreateTime | ||
jtime := *a[j].CreateTime | ||
return itime.Unix() < jtime.Unix() | ||
} | ||
|
||
func mostRecentVolume(volumes []*ec2.Volume) *ec2.Volume { | ||
sortedVolumes := volumes | ||
sort.Sort(volumeSort(sortedVolumes)) | ||
return sortedVolumes[len(sortedVolumes)-1] | ||
} | ||
|
||
func volumeDescriptionAttributes(d *schema.ResourceData, volume *ec2.Volume) error { | ||
d.SetId(*volume.VolumeId) | ||
d.Set("volume_id", volume.VolumeId) | ||
d.Set("availability_zone", volume.AvailabilityZone) | ||
d.Set("encrypted", volume.Encrypted) | ||
d.Set("iops", volume.Iops) | ||
d.Set("kms_key_id", volume.KmsKeyId) | ||
d.Set("size", volume.Size) | ||
d.Set("snapshot_id", volume.SnapshotId) | ||
d.Set("volume_type", volume.VolumeType) | ||
|
||
if err := d.Set("tags", volumeTags(volume.Tags)); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func volumeTags(m []*ec2.Tag) *schema.Set { | ||
s := &schema.Set{ | ||
F: volumeTagsHash, | ||
} | ||
for _, v := range m { | ||
tag := map[string]interface{}{ | ||
"key": *v.Key, | ||
"value": *v.Value, | ||
} | ||
s.Add(tag) | ||
} | ||
return s | ||
} | ||
|
||
func volumeTagsHash(v interface{}) int { | ||
var buf bytes.Buffer | ||
m := v.(map[string]interface{}) | ||
buf.WriteString(fmt.Sprintf("%s-", m["key"].(string))) | ||
buf.WriteString(fmt.Sprintf("%s-", m["value"].(string))) | ||
return hashcode.String(buf.String()) | ||
} |
106 changes: 106 additions & 0 deletions
106
builtin/providers/aws/data_source_aws_ebs_volume_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSEbsVolumeDataSource_basic(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCheckAwsEbsVolumeDataSourceConfig, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAwsEbsVolumeDataSourceID("data.aws_ebs_volume.ebs_volume"), | ||
resource.TestCheckResourceAttr("data.aws_ebs_volume.ebs_volume", "size", "40"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccAWSEbsVolumeDataSource_multipleFilters(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCheckAwsEbsVolumeDataSourceConfigWithMultipleFilters, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAwsEbsVolumeDataSourceID("data.aws_ebs_volume.ebs_volume"), | ||
resource.TestCheckResourceAttr("data.aws_ebs_volume.ebs_volume", "size", "10"), | ||
resource.TestCheckResourceAttr("data.aws_ebs_volume.ebs_volume", "volume_type", "gp2"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAwsEbsVolumeDataSourceID(n string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Can't find Volume data source: %s", n) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("Volume data source ID not set") | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
const testAccCheckAwsEbsVolumeDataSourceConfig = ` | ||
resource "aws_ebs_volume" "example" { | ||
availability_zone = "us-west-2a" | ||
type = "gp2" | ||
size = 40 | ||
tags { | ||
Name = "External Volume" | ||
} | ||
} | ||
data "aws_ebs_volume" "ebs_volume" { | ||
most_recent = true | ||
filter { | ||
name = "tag:Name" | ||
values = ["External Volume"] | ||
} | ||
filter { | ||
name = "volume-type" | ||
values = ["${aws_ebs_volume.example.type}"] | ||
} | ||
} | ||
` | ||
|
||
const testAccCheckAwsEbsVolumeDataSourceConfigWithMultipleFilters = ` | ||
resource "aws_ebs_volume" "external1" { | ||
availability_zone = "us-west-2a" | ||
type = "gp2" | ||
size = 10 | ||
tags { | ||
Name = "External Volume 1" | ||
} | ||
} | ||
data "aws_ebs_volume" "ebs_volume" { | ||
most_recent = true | ||
filter { | ||
name = "tag:Name" | ||
values = ["External Volume 1"] | ||
} | ||
filter { | ||
name = "size" | ||
values = ["${aws_ebs_volume.external1.size}"] | ||
} | ||
filter { | ||
name = "volume-type" | ||
values = ["${aws_ebs_volume.external1.type}"] | ||
} | ||
} | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
website/source/docs/providers/aws/d/ebs_volume.html.markdown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
--- | ||
layout: "aws" | ||
page_title: "AWS: aws_ebs_volume" | ||
sidebar_current: "docs-aws-datasource-ebs-volume" | ||
description: |- | ||
Get information on an EBS volume. | ||
--- | ||
|
||
# aws\_ebs\_volume | ||
|
||
Use this data source to get information about an EBS volume for use in other | ||
resources. | ||
|
||
## Example Usage | ||
|
||
``` | ||
data "aws_ebs_volume" "ebs_volume" { | ||
most_recent = true | ||
filter { | ||
name = "volume-type" | ||
values = ["gp2"] | ||
} | ||
filter { | ||
name = "tag:Name" | ||
values = ["Example"] | ||
} | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `most_recent` - (Optional) If more than one result is returned, use the most | ||
recent Volume. | ||
* `filter` - (Optional) One or more name/value pairs to filter off of. There are | ||
several valid keys, for a full reference, check out | ||
[describe-volumes in the AWS CLI reference][1]. | ||
|
||
|
||
## Attributes Reference | ||
|
||
The following attributes are exported: | ||
|
||
* `id` - The volume ID (e.g. vol-59fcb34e). | ||
* `volume_id` - The volume ID (e.g. vol-59fcb34e). | ||
* `availability_zone` - The AZ where the EBS volume exists. | ||
* `encrypted` - Whether the disk is encrypted. | ||
* `iops` - The amount of IOPS for the disk. | ||
* `size` - The size of the drive in GiBs. | ||
* `snapshot_id` - The snapshot_id the EBS volume is based off. | ||
* `volume_type` - The type of EBS volume. | ||
* `kms_key_id` - The ARN for the KMS encryption key. | ||
* `tags` - A mapping of tags for the resource. | ||
|
||
[1]: http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-volumes.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters