Add `aws_ami_ids` and `aws_ebs_snapshot_ids` resources (#13844)
Fixes #12081. Adds new `aws_ami_ids` and `aws_ebs_snapshot_ids` resources.
This commit is contained in:
parent
c2a1e688cb
commit
2aac8fb8fc
|
@ -0,0 +1,112 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dataSourceAwsAmiIds() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Read: dataSourceAwsAmiIdsRead,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"filter": dataSourceFiltersSchema(),
|
||||||
|
"executable_users": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
"name_regex": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
ValidateFunc: validateNameRegex,
|
||||||
|
},
|
||||||
|
"owners": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
"tags": dataSourceTagsSchema(),
|
||||||
|
"ids": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
Set: schema.HashString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataSourceAwsAmiIdsRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
executableUsers, executableUsersOk := d.GetOk("executable_users")
|
||||||
|
filters, filtersOk := d.GetOk("filter")
|
||||||
|
nameRegex, nameRegexOk := d.GetOk("name_regex")
|
||||||
|
owners, ownersOk := d.GetOk("owners")
|
||||||
|
|
||||||
|
if executableUsersOk == false && filtersOk == false && nameRegexOk == false && ownersOk == false {
|
||||||
|
return fmt.Errorf("One of executable_users, filters, name_regex, or owners must be assigned")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := &ec2.DescribeImagesInput{}
|
||||||
|
|
||||||
|
if executableUsersOk {
|
||||||
|
params.ExecutableUsers = expandStringList(executableUsers.([]interface{}))
|
||||||
|
}
|
||||||
|
if filtersOk {
|
||||||
|
params.Filters = buildAwsDataSourceFilters(filters.(*schema.Set))
|
||||||
|
}
|
||||||
|
if ownersOk {
|
||||||
|
o := expandStringList(owners.([]interface{}))
|
||||||
|
|
||||||
|
if len(o) > 0 {
|
||||||
|
params.Owners = o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := conn.DescribeImages(params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var filteredImages []*ec2.Image
|
||||||
|
imageIds := make([]string, 0)
|
||||||
|
|
||||||
|
if nameRegexOk {
|
||||||
|
r := regexp.MustCompile(nameRegex.(string))
|
||||||
|
for _, image := range resp.Images {
|
||||||
|
// Check for a very rare case where the response would include no
|
||||||
|
// image name. No name means nothing to attempt a match against,
|
||||||
|
// therefore we are skipping such image.
|
||||||
|
if image.Name == nil || *image.Name == "" {
|
||||||
|
log.Printf("[WARN] Unable to find AMI name to match against "+
|
||||||
|
"for image ID %q owned by %q, nothing to do.",
|
||||||
|
*image.ImageId, *image.OwnerId)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if r.MatchString(*image.Name) {
|
||||||
|
filteredImages = append(filteredImages, image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filteredImages = resp.Images[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, image := range filteredImages {
|
||||||
|
imageIds = append(imageIds, *image.ImageId)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(fmt.Sprintf("%d", hashcode.String(params.String())))
|
||||||
|
d.Set("ids", imageIds)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsAmiIds_basic(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccDataSourceAwsAmiIdsConfig_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAwsAmiDataSourceID("data.aws_ami_ids.ubuntu"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsAmiIds_empty(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccDataSourceAwsAmiIdsConfig_empty,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAwsAmiDataSourceID("data.aws_ami_ids.empty"),
|
||||||
|
resource.TestCheckResourceAttr("data.aws_ami_ids.empty", "ids.#", "0"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccDataSourceAwsAmiIdsConfig_basic = `
|
||||||
|
data "aws_ami_ids" "ubuntu" {
|
||||||
|
owners = ["099720109477"]
|
||||||
|
|
||||||
|
filter {
|
||||||
|
name = "name"
|
||||||
|
values = ["ubuntu/images/ubuntu-*-*-amd64-server-*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccDataSourceAwsAmiIdsConfig_empty = `
|
||||||
|
data "aws_ami_ids" "empty" {
|
||||||
|
filter {
|
||||||
|
name = "name"
|
||||||
|
values = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,78 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dataSourceAwsEbsSnapshotIds() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Read: dataSourceAwsEbsSnapshotIdsRead,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"filter": dataSourceFiltersSchema(),
|
||||||
|
"owners": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
"restorable_by_user_ids": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
"tags": dataSourceTagsSchema(),
|
||||||
|
"ids": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
Set: schema.HashString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataSourceAwsEbsSnapshotIdsRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
restorableUsers, restorableUsersOk := d.GetOk("restorable_by_user_ids")
|
||||||
|
filters, filtersOk := d.GetOk("filter")
|
||||||
|
owners, ownersOk := d.GetOk("owners")
|
||||||
|
|
||||||
|
if restorableUsers == false && filtersOk == false && ownersOk == false {
|
||||||
|
return fmt.Errorf("One of filters, restorable_by_user_ids, or owners must be assigned")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := &ec2.DescribeSnapshotsInput{}
|
||||||
|
|
||||||
|
if restorableUsersOk {
|
||||||
|
params.RestorableByUserIds = expandStringList(restorableUsers.([]interface{}))
|
||||||
|
}
|
||||||
|
if filtersOk {
|
||||||
|
params.Filters = buildAwsDataSourceFilters(filters.(*schema.Set))
|
||||||
|
}
|
||||||
|
if ownersOk {
|
||||||
|
params.OwnerIds = expandStringList(owners.([]interface{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := conn.DescribeSnapshots(params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshotIds := make([]string, 0)
|
||||||
|
|
||||||
|
for _, snapshot := range resp.Snapshots {
|
||||||
|
snapshotIds = append(snapshotIds, *snapshot.SnapshotId)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(fmt.Sprintf("%d", hashcode.String(params.String())))
|
||||||
|
d.Set("ids", snapshotIds)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsEbsSnapshotIds_basic(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccDataSourceAwsEbsSnapshotIdsConfig_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAwsEbsSnapshotDataSourceID("data.aws_ebs_snapshot_ids.test"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsEbsSnapshotIds_empty(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccDataSourceAwsEbsSnapshotIdsConfig_empty,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAwsEbsSnapshotDataSourceID("data.aws_ebs_snapshot_ids.empty"),
|
||||||
|
resource.TestCheckResourceAttr("data.aws_ebs_snapshot_ids.empty", "ids.#", "0"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccDataSourceAwsEbsSnapshotIdsConfig_basic = `
|
||||||
|
resource "aws_ebs_volume" "test" {
|
||||||
|
availability_zone = "us-west-2a"
|
||||||
|
size = 40
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ebs_snapshot" "test" {
|
||||||
|
volume_id = "${aws_ebs_volume.test.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_ebs_snapshot_ids" "test" {
|
||||||
|
owners = ["self"]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccDataSourceAwsEbsSnapshotIdsConfig_empty = `
|
||||||
|
data "aws_ebs_snapshot_ids" "empty" {
|
||||||
|
owners = ["000000000000"]
|
||||||
|
}
|
||||||
|
`
|
|
@ -44,7 +44,7 @@ func testAccCheckAwsEbsSnapshotDataSourceID(n string) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[n]
|
rs, ok := s.RootModule().Resources[n]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Can't find Volume data source: %s", n)
|
return fmt.Errorf("Can't find snapshot data source: %s", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rs.Primary.ID == "" {
|
if rs.Primary.ID == "" {
|
||||||
|
|
|
@ -163,6 +163,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"aws_alb": dataSourceAwsAlb(),
|
"aws_alb": dataSourceAwsAlb(),
|
||||||
"aws_alb_listener": dataSourceAwsAlbListener(),
|
"aws_alb_listener": dataSourceAwsAlbListener(),
|
||||||
"aws_ami": dataSourceAwsAmi(),
|
"aws_ami": dataSourceAwsAmi(),
|
||||||
|
"aws_ami_ids": dataSourceAwsAmiIds(),
|
||||||
"aws_autoscaling_groups": dataSourceAwsAutoscalingGroups(),
|
"aws_autoscaling_groups": dataSourceAwsAutoscalingGroups(),
|
||||||
"aws_availability_zone": dataSourceAwsAvailabilityZone(),
|
"aws_availability_zone": dataSourceAwsAvailabilityZone(),
|
||||||
"aws_availability_zones": dataSourceAwsAvailabilityZones(),
|
"aws_availability_zones": dataSourceAwsAvailabilityZones(),
|
||||||
|
@ -172,6 +173,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"aws_cloudformation_stack": dataSourceAwsCloudFormationStack(),
|
"aws_cloudformation_stack": dataSourceAwsCloudFormationStack(),
|
||||||
"aws_db_instance": dataSourceAwsDbInstance(),
|
"aws_db_instance": dataSourceAwsDbInstance(),
|
||||||
"aws_ebs_snapshot": dataSourceAwsEbsSnapshot(),
|
"aws_ebs_snapshot": dataSourceAwsEbsSnapshot(),
|
||||||
|
"aws_ebs_snapshot_ids": dataSourceAwsEbsSnapshotIds(),
|
||||||
"aws_ebs_volume": dataSourceAwsEbsVolume(),
|
"aws_ebs_volume": dataSourceAwsEbsVolume(),
|
||||||
"aws_ecs_cluster": dataSourceAwsEcsCluster(),
|
"aws_ecs_cluster": dataSourceAwsEcsCluster(),
|
||||||
"aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(),
|
"aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(),
|
||||||
|
|
|
@ -59,7 +59,8 @@ options to narrow down the list AWS returns.
|
||||||
|
|
||||||
~> **NOTE:** If more or less than a single match is returned by the search,
|
~> **NOTE:** If more or less than a single match is returned by the search,
|
||||||
Terraform will fail. Ensure that your search is specific enough to return
|
Terraform will fail. Ensure that your search is specific enough to return
|
||||||
a single AMI ID only, or use `most_recent` to choose the most recent one.
|
a single AMI ID only, or use `most_recent` to choose the most recent one. If
|
||||||
|
you want to match multiple AMIs, use the `aws_ami_ids` data source instead.
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_ami_ids"
|
||||||
|
sidebar_current: "docs-aws-datasource-ami-ids"
|
||||||
|
description: |-
|
||||||
|
Provides a list of AMI IDs.
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_ami_ids
|
||||||
|
|
||||||
|
Use this data source to get a list of AMI IDs matching the specified criteria.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
data "aws_ami_ids" "ubuntu" {
|
||||||
|
owners = ["099720109477"]
|
||||||
|
|
||||||
|
filter {
|
||||||
|
name = "name"
|
||||||
|
values = ["ubuntu/images/ubuntu-*-*-amd64-server-*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
* `executable_users` - (Optional) Limit search to users with *explicit* launch
|
||||||
|
permission on the image. Valid items are the numeric account ID or `self`.
|
||||||
|
|
||||||
|
* `filter` - (Optional) One or more name/value pairs to filter off of. There
|
||||||
|
are several valid keys, for a full reference, check out
|
||||||
|
[describe-images in the AWS CLI reference][1].
|
||||||
|
|
||||||
|
* `owners` - (Optional) Limit search to specific AMI owners. Valid items are
|
||||||
|
the numeric account ID, `amazon`, or `self`.
|
||||||
|
|
||||||
|
* `name_regex` - (Optional) A regex string to apply to the AMI list returned
|
||||||
|
by AWS. This allows more advanced filtering not supported from the AWS API.
|
||||||
|
This filtering is done locally on what AWS returns, and could have a performance
|
||||||
|
impact if the result is large. It is recommended to combine this with other
|
||||||
|
options to narrow down the list AWS returns.
|
||||||
|
|
||||||
|
~> **NOTE:** At least one of `executable_users`, `filter`, `owners` or
|
||||||
|
`name_regex` must be specified.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
`ids` is set to the list of AMI IDs.
|
||||||
|
|
||||||
|
[1]: http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_ebs_snapshot_ids"
|
||||||
|
sidebar_current: "docs-aws-datasource-ebs-snapshot-ids"
|
||||||
|
description: |-
|
||||||
|
Provides a list of EBS snapshot IDs.
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_ebs\_snapshot\_ids
|
||||||
|
|
||||||
|
Use this data source to get a list of EBS Snapshot IDs matching the specified
|
||||||
|
criteria.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
data "aws_ebs_snapshot_ids" "ebs_volumes" {
|
||||||
|
owners = ["self"]
|
||||||
|
|
||||||
|
filter {
|
||||||
|
name = "volume-size"
|
||||||
|
values = ["40"]
|
||||||
|
}
|
||||||
|
|
||||||
|
filter {
|
||||||
|
name = "tag:Name"
|
||||||
|
values = ["Example"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `owners` - (Optional) Returns the snapshots owned by the specified owner id. Multiple owners can be specified.
|
||||||
|
|
||||||
|
* `restorable_by_user_ids` - (Optional) One or more AWS accounts IDs that can create volumes from the snapshot.
|
||||||
|
|
||||||
|
* `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
|
||||||
|
|
||||||
|
`ids` is set to the list of EBS snapshot IDs.
|
||||||
|
|
||||||
|
[1]: http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-snapshots.html
|
Loading…
Reference in New Issue