provider/aws: add local name filter to aws_ami datasource

In cases where the filters provided by AWS against the name of an AMI are not
sufficient, allow adding a "local_name_filter" which is a regex that is used
to filter the AMIs returned by amazon.
This commit is contained in:
Shawn Silva 2016-08-22 19:32:32 -04:00
parent 38289ddbd5
commit 6977fff406
3 changed files with 61 additions and 8 deletions

View File

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"log"
"regexp"
"sort"
"time"
@ -43,6 +44,11 @@ func dataSourceAwsAmi() *schema.Resource {
},
},
},
"local_name_filter": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"most_recent": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
@ -206,10 +212,11 @@ func dataSourceAwsAmiRead(d *schema.ResourceData, meta interface{}) error {
executableUsers, executableUsersOk := d.GetOk("executable_users")
filters, filtersOk := d.GetOk("filter")
localNameFilter, localNameFilterOk := d.GetOk("local_name_filter")
owners, ownersOk := d.GetOk("owners")
if executableUsersOk == false && filtersOk == false && ownersOk == false {
return fmt.Errorf("One of executable_users, filters, or owners must be assigned")
if executableUsersOk == false && filtersOk == false && localNameFilterOk == false && ownersOk == false {
return fmt.Errorf("One of executable_users, filters, local_name_filter, or owners must be assigned")
}
params := &ec2.DescribeImagesInput{}
@ -227,20 +234,33 @@ func dataSourceAwsAmiRead(d *schema.ResourceData, meta interface{}) error {
if err != nil {
return err
}
var filteredImages []*ec2.Image
if localNameFilterOk == true {
r := regexp.MustCompile(localNameFilter.(string))
for _, image := range resp.Images {
if r.MatchString(*image.Name) == true {
filteredImages = append(filteredImages, image)
}
}
} else {
filteredImages = resp.Images[:]
}
var image *ec2.Image
if len(resp.Images) < 1 {
if len(filteredImages) < 1 {
return fmt.Errorf("Your query returned no results. Please change your filters and try again.")
} else if len(resp.Images) > 1 {
} else if len(filteredImages) > 1 {
if (d.Get("most_recent").(bool)) == true {
log.Printf("[DEBUG] aws_ami - multiple results found and most_recent is set")
image = mostRecentAmi(resp.Images)
image = mostRecentAmi(filteredImages)
} else {
log.Printf("[DEBUG] aws_ami - multiple results found and most_recent not set")
return fmt.Errorf("Your query returned more than one result. Please try a more specific search, or set most_recent to true.")
}
} else {
log.Printf("[DEBUG] aws_ami - Single AMI found: %s", *resp.Images[0].ImageId)
image = resp.Images[0]
log.Printf("[DEBUG] aws_ami - Single AMI found: %s", *filteredImages[0].ImageId)
image = filteredImages[0]
}
return amiDescriptionAttributes(d, image)
}

View File

@ -139,6 +139,22 @@ func TestAccAWSAmiDataSource_owners(t *testing.T) {
})
}
func TestAccAWSAmiDataSource_localNameFilter(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckAwsAmiDataSourceLocalNameFilterConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsAmiDataSourceID("data.aws_ami.local_filtered_ami"),
resource.TestMatchResourceAttr("data.aws_ami.local_filtered_ami", "image_id", regexp.MustCompile("^ami-")),
),
},
},
})
}
func testAccCheckAwsAmiDataSourceDestroy(s *terraform.State) error {
return nil
}
@ -245,3 +261,16 @@ data "aws_ami" "amazon_ami" {
owners = ["amazon"]
}
`
// Testing local_name_filter parameter
const testAccCheckAwsAmiDataSourceLocalNameFilterConfig = `
data "aws_ami" "local_filtered_ami" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn-ami-*"]
}
local_name_filter = "^amzn-ami-\\d{3}[5].*-ecs-optimized"
}
`

View File

@ -8,7 +8,7 @@ description: |-
# aws\_ami
Use this data source to get the ID of a registered AMI for use in other
Use this data source to get the ID of a registered AMI for use in other
resources.
## Example Usage
@ -25,6 +25,7 @@ data "aws_ami" "nat_ami" {
name = "name"
values = ["amzn-ami-vpc-nat*"]
}
local_name_filter = "^myami-\\d{3}"
owners = ["self"]
}
```
@ -41,6 +42,9 @@ recent AMI.
several valid keys, for a full reference, check out
[describe-images in the AWS CLI reference][1].
* `local_name_filter` - (Optional) A regex string to apply to the AMI list returned
by AWS. This allows more advanced filtering not supported from the AWS API.
* `owners` - (Optional) Limit search to specific AMI owners. Valid items are the numeric
account ID, `amazon`, or `self`.