Add state filter to aws_availability_zones data source. (#7965)
* Add state filter to aws_availability_zones data source. This commit adds an ability to filter Availability Zones based on state, where by default it would only list available zones. Be advised that this does not always works reliably for an older accounts which have been created in the pre-VPC era of EC2. These accounts tends to retrieve availability zones that are not VPC-enabled, thus creation of a custom subnet within such Availability Zone would result in a failure. Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com> * Update documentation for aws_availability_zones data source. Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com> * Do not filter on state by default. This commit makes the state filter applicable only when set. Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com>
This commit is contained in:
parent
256190a84c
commit
19800b8e26
|
@ -21,6 +21,11 @@ func dataSourceAwsAvailabilityZones() *schema.Resource {
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
},
|
},
|
||||||
|
"state": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ValidateFunc: validateStateType,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,25 +33,55 @@ func dataSourceAwsAvailabilityZones() *schema.Resource {
|
||||||
func dataSourceAwsAvailabilityZonesRead(d *schema.ResourceData, meta interface{}) error {
|
func dataSourceAwsAvailabilityZonesRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
conn := meta.(*AWSClient).ec2conn
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
log.Printf("[DEBUG] Reading availability zones")
|
log.Printf("[DEBUG] Reading Availability Zones.")
|
||||||
d.SetId(time.Now().UTC().String())
|
d.SetId(time.Now().UTC().String())
|
||||||
|
|
||||||
req := &ec2.DescribeAvailabilityZonesInput{DryRun: aws.Bool(false)}
|
request := &ec2.DescribeAvailabilityZonesInput{}
|
||||||
azresp, err := conn.DescribeAvailabilityZones(req)
|
|
||||||
if err != nil {
|
if v, ok := d.GetOk("state"); ok {
|
||||||
return fmt.Errorf("Error listing availability zones: %s", err)
|
request.Filters = []*ec2.Filter{
|
||||||
|
&ec2.Filter{
|
||||||
|
Name: aws.String("state"),
|
||||||
|
Values: []*string{aws.String(v.(string))},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := make([]string, len(azresp.AvailabilityZones))
|
log.Printf("[DEBUG] Availability Zones request options: %#v", *request)
|
||||||
for i, v := range azresp.AvailabilityZones {
|
|
||||||
|
resp, err := conn.DescribeAvailabilityZones(request)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error fetching Availability Zones: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
raw := make([]string, len(resp.AvailabilityZones))
|
||||||
|
for i, v := range resp.AvailabilityZones {
|
||||||
raw[i] = *v.ZoneName
|
raw[i] = *v.ZoneName
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(raw)
|
sort.Strings(raw)
|
||||||
|
|
||||||
if err := d.Set("names", raw); err != nil {
|
if err := d.Set("names", raw); err != nil {
|
||||||
return fmt.Errorf("[WARN] Error setting availability zones")
|
return fmt.Errorf("[WARN] Error setting Availability Zones: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateStateType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
|
value := v.(string)
|
||||||
|
|
||||||
|
validState := map[string]bool{
|
||||||
|
"available": true,
|
||||||
|
"information": true,
|
||||||
|
"impaired": true,
|
||||||
|
"unavailable": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validState[value] {
|
||||||
|
errors = append(errors, fmt.Errorf(
|
||||||
|
"%q contains an invalid Availability Zone state %q. Valid states are: %q, %q, %q and %q.",
|
||||||
|
k, value, "available", "information", "impaired", "unavailable"))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,12 @@ func TestAccAWSAvailabilityZones_basic(t *testing.T) {
|
||||||
testAccCheckAwsAvailabilityZonesMeta("data.aws_availability_zones.availability_zones"),
|
testAccCheckAwsAvailabilityZonesMeta("data.aws_availability_zones.availability_zones"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckAwsAvailabilityZonesStateConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAwsAvailabilityZoneState("data.aws_availability_zones.state_filter"),
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -34,7 +40,7 @@ func testAccCheckAwsAvailabilityZonesMeta(n string) resource.TestCheckFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
if rs.Primary.ID == "" {
|
if rs.Primary.ID == "" {
|
||||||
return fmt.Errorf("AZ resource ID not set")
|
return fmt.Errorf("AZ resource ID not set.")
|
||||||
}
|
}
|
||||||
|
|
||||||
actual, err := testAccCheckAwsAvailabilityZonesBuildAvailable(rs.Primary.Attributes)
|
actual, err := testAccCheckAwsAvailabilityZonesBuildAvailable(rs.Primary.Attributes)
|
||||||
|
@ -51,10 +57,33 @@ func testAccCheckAwsAvailabilityZonesMeta(n string) resource.TestCheckFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAccCheckAwsAvailabilityZoneState(n string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Can't find AZ resource: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("AZ resource ID not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := rs.Primary.Attributes["state"]; !ok {
|
||||||
|
return fmt.Errorf("AZs state filter is missing, should be set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := testAccCheckAwsAvailabilityZonesBuildAvailable(rs.Primary.Attributes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckAwsAvailabilityZonesBuildAvailable(attrs map[string]string) ([]string, error) {
|
func testAccCheckAwsAvailabilityZonesBuildAvailable(attrs map[string]string) ([]string, error) {
|
||||||
v, ok := attrs["names.#"]
|
v, ok := attrs["names.#"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("Available AZ list is missing")
|
return nil, fmt.Errorf("Available AZ list is missing.")
|
||||||
}
|
}
|
||||||
qty, err := strconv.Atoi(v)
|
qty, err := strconv.Atoi(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -67,7 +96,7 @@ func testAccCheckAwsAvailabilityZonesBuildAvailable(attrs map[string]string) ([]
|
||||||
for n := range zones {
|
for n := range zones {
|
||||||
zone, ok := attrs["names."+strconv.Itoa(n)]
|
zone, ok := attrs["names."+strconv.Itoa(n)]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("AZ list corrupt, this is definitely a bug")
|
return nil, fmt.Errorf("AZ list corrupt, this is definitely a bug.")
|
||||||
}
|
}
|
||||||
zones[n] = zone
|
zones[n] = zone
|
||||||
}
|
}
|
||||||
|
@ -75,6 +104,11 @@ func testAccCheckAwsAvailabilityZonesBuildAvailable(attrs map[string]string) ([]
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAccCheckAwsAvailabilityZonesConfig = `
|
const testAccCheckAwsAvailabilityZonesConfig = `
|
||||||
data "aws_availability_zones" "availability_zones" {
|
data "aws_availability_zones" "availability_zones" { }
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccCheckAwsAvailabilityZonesStateConfig = `
|
||||||
|
data "aws_availability_zones" "state_filter" {
|
||||||
|
state = "available"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -3,7 +3,7 @@ layout: "aws"
|
||||||
page_title: "AWS: aws_availability_zones"
|
page_title: "AWS: aws_availability_zones"
|
||||||
sidebar_current: "docs-aws-datasource-availability-zones"
|
sidebar_current: "docs-aws-datasource-availability-zones"
|
||||||
description: |-
|
description: |-
|
||||||
Provides a list of availability zones which can be used by an AWS account
|
Provides a list of Availability Zones which can be used by an AWS account.
|
||||||
---
|
---
|
||||||
|
|
||||||
# aws\_availability\_zones
|
# aws\_availability\_zones
|
||||||
|
@ -35,10 +35,15 @@ resource "aws_subnet" "secondary" {
|
||||||
|
|
||||||
## Argument Reference
|
## Argument Reference
|
||||||
|
|
||||||
There are no arguments for this data source.
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `state` - (Optional) Allows to filter list of Availability Zones based on their
|
||||||
|
current state. Can be either `"available"`, `"information"`, `"impaired"` or
|
||||||
|
`"unavailable"`. By default the list includes a complete set of Availability Zones
|
||||||
|
to which the underlying AWS account has access, regardless of their state.
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
The following attributes are exported:
|
The following attributes are exported:
|
||||||
|
|
||||||
* `names` - A list of the availability zone names available to the account.
|
* `names` - A list of the Availability Zone names available to the account.
|
||||||
|
|
Loading…
Reference in New Issue