Skip to content

Commit

Permalink
data-source/aws_availability_zone: Add parent_zone_id, `parent_zone…
Browse files Browse the repository at this point in the history
…_name`, and `zone_type` attributes (additional support for Local and Wavelength Zones) (#16770)

* d/aws_availability_zone: Add 'zone_type' attribute.

Acceptance test output:

$ make testacc TEST=./aws/ TESTARGS='-run=TestAccDataSourceAwsAvailabilityZone_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccDataSourceAwsAvailabilityZone_ -timeout 120m
=== RUN   TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== PAUSE TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== RUN   TestAccDataSourceAwsAvailabilityZone_Filter
=== PAUSE TestAccDataSourceAwsAvailabilityZone_Filter
=== RUN   TestAccDataSourceAwsAvailabilityZone_Name
=== PAUSE TestAccDataSourceAwsAvailabilityZone_Name
=== RUN   TestAccDataSourceAwsAvailabilityZone_ZoneId
=== PAUSE TestAccDataSourceAwsAvailabilityZone_ZoneId
=== CONT  TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== CONT  TestAccDataSourceAwsAvailabilityZone_Filter
=== CONT  TestAccDataSourceAwsAvailabilityZone_ZoneId
=== CONT  TestAccDataSourceAwsAvailabilityZone_Name
--- PASS: TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones (14.09s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_Filter (15.90s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_ZoneId (16.10s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_Name (16.13s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	16.194s

* d/aws_availability_zone: Add Local Zone test.

Acceptance test output:

$ make testacc TEST=./aws/ TESTARGS='-run=TestAccDataSourceAwsAvailabilityZone_LocalZone'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccDataSourceAwsAvailabilityZone_LocalZone -timeout 120m
=== RUN   TestAccDataSourceAwsAvailabilityZone_LocalZone
=== PAUSE TestAccDataSourceAwsAvailabilityZone_LocalZone
=== CONT  TestAccDataSourceAwsAvailabilityZone_LocalZone
--- PASS: TestAccDataSourceAwsAvailabilityZone_LocalZone (10.55s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	10.625s

* d/aws_availability_zone: Add Wavelength Zone test.

Acceptance test output:

$ make testacc TEST=./aws/ TESTARGS='-run=TestAccDataSourceAwsAvailabilityZone_WavelengthZone'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccDataSourceAwsAvailabilityZone_WavelengthZone -timeout 120m
=== RUN   TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== PAUSE TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== CONT  TestAccDataSourceAwsAvailabilityZone_WavelengthZone
--- PASS: TestAccDataSourceAwsAvailabilityZone_WavelengthZone (10.63s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	10.711s

* d/aws_availability_zone: Add 'parent_zone_id' and 'parent_zone_name' attributes.

Acceptance test output:

$ make testacc TEST=./aws/ TESTARGS='-run=TestAccDataSourceAwsAvailabilityZone_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccDataSourceAwsAvailabilityZone_ -timeout 120m
=== RUN   TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== PAUSE TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== RUN   TestAccDataSourceAwsAvailabilityZone_Filter
=== PAUSE TestAccDataSourceAwsAvailabilityZone_Filter
=== RUN   TestAccDataSourceAwsAvailabilityZone_LocalZone
=== PAUSE TestAccDataSourceAwsAvailabilityZone_LocalZone
=== RUN   TestAccDataSourceAwsAvailabilityZone_Name
=== PAUSE TestAccDataSourceAwsAvailabilityZone_Name
=== RUN   TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== PAUSE TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== RUN   TestAccDataSourceAwsAvailabilityZone_ZoneId
=== PAUSE TestAccDataSourceAwsAvailabilityZone_ZoneId
=== CONT  TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== CONT  TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== CONT  TestAccDataSourceAwsAvailabilityZone_ZoneId
=== CONT  TestAccDataSourceAwsAvailabilityZone_LocalZone
=== CONT  TestAccDataSourceAwsAvailabilityZone_Name
=== CONT  TestAccDataSourceAwsAvailabilityZone_Filter
--- PASS: TestAccDataSourceAwsAvailabilityZone_Filter (19.67s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones (21.28s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_WavelengthZone (21.55s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_Name (21.65s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_ZoneId (21.69s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_LocalZone (21.70s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	21.778s

* d/aws_availability_zone: Remove leading '-' from 'name_suffix' for Local and Wavelength Zones.

Acceptance test output:

$ make testacc TEST=./aws/ TESTARGS='-run=TestAccDataSourceAwsAvailabilityZone_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccDataSourceAwsAvailabilityZone_ -timeout 120m
=== RUN   TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== PAUSE TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== RUN   TestAccDataSourceAwsAvailabilityZone_Filter
=== PAUSE TestAccDataSourceAwsAvailabilityZone_Filter
=== RUN   TestAccDataSourceAwsAvailabilityZone_LocalZone
=== PAUSE TestAccDataSourceAwsAvailabilityZone_LocalZone
=== RUN   TestAccDataSourceAwsAvailabilityZone_Name
=== PAUSE TestAccDataSourceAwsAvailabilityZone_Name
=== RUN   TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== PAUSE TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== RUN   TestAccDataSourceAwsAvailabilityZone_ZoneId
=== PAUSE TestAccDataSourceAwsAvailabilityZone_ZoneId
=== CONT  TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones
=== CONT  TestAccDataSourceAwsAvailabilityZone_ZoneId
=== CONT  TestAccDataSourceAwsAvailabilityZone_WavelengthZone
=== CONT  TestAccDataSourceAwsAvailabilityZone_Name
=== CONT  TestAccDataSourceAwsAvailabilityZone_LocalZone
=== CONT  TestAccDataSourceAwsAvailabilityZone_Filter
--- PASS: TestAccDataSourceAwsAvailabilityZone_Name (17.92s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_ZoneId (19.40s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_WavelengthZone (20.22s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_LocalZone (20.37s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones (20.69s)
--- PASS: TestAccDataSourceAwsAvailabilityZone_Filter (20.69s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	20.770s
  • Loading branch information
ewbankkit committed Dec 15, 2020
1 parent 174fd13 commit 896c7d3
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 13 deletions.
20 changes: 19 additions & 1 deletion aws/data_source_aws_availability_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"log"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
Expand Down Expand Up @@ -40,6 +41,14 @@ func dataSourceAwsAvailabilityZone() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"parent_zone_id": {
Type: schema.TypeString,
Computed: true,
},
"parent_zone_name": {
Type: schema.TypeString,
Computed: true,
},
"region": {
Type: schema.TypeString,
Computed: true,
Expand All @@ -54,6 +63,10 @@ func dataSourceAwsAvailabilityZone() *schema.Resource {
Optional: true,
Computed: true,
},
"zone_type": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand Down Expand Up @@ -108,17 +121,22 @@ func dataSourceAwsAvailabilityZoneRead(d *schema.ResourceData, meta interface{})
// the AZ suffix alone, without the region name.
// This can be used e.g. to create lookup tables by AZ letter that
// work regardless of region.
nameSuffix := (*az.ZoneName)[len(*az.RegionName):]
nameSuffix := aws.StringValue(az.ZoneName)[len(aws.StringValue(az.RegionName)):]
// For Local and Wavelength zones, remove any leading "-".
nameSuffix = strings.TrimLeft(nameSuffix, "-")

d.SetId(aws.StringValue(az.ZoneName))
d.Set("group_name", az.GroupName)
d.Set("name", az.ZoneName)
d.Set("name_suffix", nameSuffix)
d.Set("network_border_group", az.NetworkBorderGroup)
d.Set("opt_in_status", az.OptInStatus)
d.Set("parent_zone_id", az.ParentZoneId)
d.Set("parent_zone_name", az.ParentZoneName)
d.Set("region", az.RegionName)
d.Set("state", az.State)
d.Set("zone_id", az.ZoneId)
d.Set("zone_type", az.ZoneType)

return nil
}
147 changes: 135 additions & 12 deletions aws/data_source_aws_availability_zone_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package aws

import (
"fmt"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

Expand All @@ -22,9 +24,12 @@ func TestAccDataSourceAwsAvailabilityZone_AllAvailabilityZones(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "name", availabilityZonesDataSourceName, "names.0"),
resource.TestMatchResourceAttr(dataSourceName, "name_suffix", regexp.MustCompile(`^[a-z]$`)),
resource.TestCheckResourceAttr(dataSourceName, "network_border_group", testAccGetRegion()),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", "opt-in-not-required"),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", ec2.AvailabilityZoneOptInStatusOptInNotRequired),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_id", ""),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_name", ""),
resource.TestCheckResourceAttr(dataSourceName, "region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(dataSourceName, "zone_id", availabilityZonesDataSourceName, "zone_ids.0"),
resource.TestCheckResourceAttr(dataSourceName, "zone_type", "availability-zone"),
),
},
},
Expand All @@ -46,9 +51,39 @@ func TestAccDataSourceAwsAvailabilityZone_Filter(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "name", availabilityZonesDataSourceName, "names.0"),
resource.TestMatchResourceAttr(dataSourceName, "name_suffix", regexp.MustCompile(`^[a-z]$`)),
resource.TestCheckResourceAttr(dataSourceName, "network_border_group", testAccGetRegion()),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", "opt-in-not-required"),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", ec2.AvailabilityZoneOptInStatusOptInNotRequired),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_id", ""),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_name", ""),
resource.TestCheckResourceAttr(dataSourceName, "region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(dataSourceName, "zone_id", availabilityZonesDataSourceName, "zone_ids.0"),
resource.TestCheckResourceAttr(dataSourceName, "zone_type", "availability-zone"),
),
},
},
})
}

func TestAccDataSourceAwsAvailabilityZone_LocalZone(t *testing.T) {
availabilityZonesDataSourceName := "data.aws_availability_zones.available"
dataSourceName := "data.aws_availability_zone.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSLocalZoneAvailable(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsAvailabilityZoneConfigZoneType("local-zone"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(dataSourceName, "group_name"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", availabilityZonesDataSourceName, "names.0"),
resource.TestMatchResourceAttr(dataSourceName, "name_suffix", regexp.MustCompile(`^[a-z0-9][a-z0-9-]+$`)),
resource.TestCheckResourceAttrSet(dataSourceName, "network_border_group"),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", ec2.AvailabilityZoneOptInStatusOptedIn),
resource.TestCheckResourceAttrSet(dataSourceName, "parent_zone_id"),
resource.TestCheckResourceAttrSet(dataSourceName, "parent_zone_name"),
resource.TestCheckResourceAttr(dataSourceName, "region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(dataSourceName, "zone_id", availabilityZonesDataSourceName, "zone_ids.0"),
resource.TestCheckResourceAttr(dataSourceName, "zone_type", "local-zone"),
),
},
},
Expand All @@ -70,9 +105,39 @@ func TestAccDataSourceAwsAvailabilityZone_Name(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "name", availabilityZonesDataSourceName, "names.0"),
resource.TestMatchResourceAttr(dataSourceName, "name_suffix", regexp.MustCompile(`^[a-z]$`)),
resource.TestCheckResourceAttr(dataSourceName, "network_border_group", testAccGetRegion()),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", "opt-in-not-required"),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", ec2.AvailabilityZoneOptInStatusOptInNotRequired),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_id", ""),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_name", ""),
resource.TestCheckResourceAttr(dataSourceName, "region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(dataSourceName, "zone_id", availabilityZonesDataSourceName, "zone_ids.0"),
resource.TestCheckResourceAttr(dataSourceName, "zone_type", "availability-zone"),
),
},
},
})
}

func TestAccDataSourceAwsAvailabilityZone_WavelengthZone(t *testing.T) {
availabilityZonesDataSourceName := "data.aws_availability_zones.available"
dataSourceName := "data.aws_availability_zone.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWavelengthZoneAvailable(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsAvailabilityZoneConfigZoneType("wavelength-zone"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(dataSourceName, "group_name"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", availabilityZonesDataSourceName, "names.0"),
resource.TestMatchResourceAttr(dataSourceName, "name_suffix", regexp.MustCompile(`^[a-z0-9][a-z0-9-]+$`)),
resource.TestCheckResourceAttrSet(dataSourceName, "network_border_group"),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", ec2.AvailabilityZoneOptInStatusOptedIn),
resource.TestCheckResourceAttrSet(dataSourceName, "parent_zone_id"),
resource.TestCheckResourceAttrSet(dataSourceName, "parent_zone_name"),
resource.TestCheckResourceAttr(dataSourceName, "region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(dataSourceName, "zone_id", availabilityZonesDataSourceName, "zone_ids.0"),
resource.TestCheckResourceAttr(dataSourceName, "zone_type", "wavelength-zone"),
),
},
},
Expand All @@ -94,47 +159,105 @@ func TestAccDataSourceAwsAvailabilityZone_ZoneId(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "name", availabilityZonesDataSourceName, "names.0"),
resource.TestMatchResourceAttr(dataSourceName, "name_suffix", regexp.MustCompile(`^[a-z]$`)),
resource.TestCheckResourceAttr(dataSourceName, "network_border_group", testAccGetRegion()),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", "opt-in-not-required"),
resource.TestCheckResourceAttr(dataSourceName, "opt_in_status", ec2.AvailabilityZoneOptInStatusOptInNotRequired),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_id", ""),
resource.TestCheckResourceAttr(dataSourceName, "parent_zone_name", ""),
resource.TestCheckResourceAttr(dataSourceName, "region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(dataSourceName, "zone_id", availabilityZonesDataSourceName, "zone_ids.0"),
resource.TestCheckResourceAttr(dataSourceName, "zone_type", "availability-zone"),
),
},
},
})
}

func testAccPreCheckAWSLocalZoneAvailable(t *testing.T) {
conn := testAccProvider.Meta().(*AWSClient).ec2conn

input := &ec2.DescribeAvailabilityZonesInput{
Filters: buildEC2AttributeFilterList(map[string]string{
"zone-type": "local-zone",
"opt-in-status": "opted-in",
}),
}

output, err := conn.DescribeAvailabilityZones(input)

if testAccPreCheckSkipError(err) {
t.Skipf("skipping acceptance testing: %s", err)
}

if err != nil {
t.Fatalf("unexpected PreCheck error: %s", err)
}

if output == nil || len(output.AvailabilityZones) == 0 {
t.Skip("skipping since no Local Zones are available")
}
}

func testAccDataSourceAwsAvailabilityZoneConfigAllAvailabilityZones() string {
return testAccAvailableAZsNoOptInConfig() + `
return composeConfig(
testAccAvailableAZsNoOptInConfig(),
`
data "aws_availability_zone" "test" {
all_availability_zones = true
name = data.aws_availability_zones.available.names[0]
}
`
`)
}

func testAccDataSourceAwsAvailabilityZoneConfigFilter() string {
return testAccAvailableAZsNoOptInConfig() + `
return composeConfig(
testAccAvailableAZsNoOptInConfig(),
`
data "aws_availability_zone" "test" {
filter {
name = "zone-name"
values = [data.aws_availability_zones.available.names[0]]
}
}
`
`)
}

func testAccDataSourceAwsAvailabilityZoneConfigName() string {
return testAccAvailableAZsNoOptInConfig() + `
return composeConfig(
testAccAvailableAZsNoOptInConfig(),
`
data "aws_availability_zone" "test" {
name = data.aws_availability_zones.available.names[0]
}
`
`)
}

func testAccDataSourceAwsAvailabilityZoneConfigZoneId() string {
return testAccAvailableAZsNoOptInConfig() + `
return composeConfig(
testAccAvailableAZsNoOptInConfig(),
`
data "aws_availability_zone" "test" {
zone_id = data.aws_availability_zones.available.zone_ids[0]
}
`)
}

func testAccDataSourceAwsAvailabilityZoneConfigZoneType(zoneType string) string {
return fmt.Sprintf(`
data "aws_availability_zones" "available" {
state = "available"
filter {
name = "zone-type"
values = [%[1]q]
}
filter {
name = "opt-in-status"
values = ["opted-in"]
}
}
data "aws_availability_zone" "test" {
zone_id = data.aws_availability_zones.available.zone_ids[0]
}
`
`, zoneType)
}
5 changes: 5 additions & 0 deletions website/docs/d/availability_zone.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ In addition to all arguments above, the following attributes are exported:

* `group_name` - For Availability Zones, this is the same value as the Region name. For Local Zones, the name of the associated group, for example `us-west-2-lax-1`.
* `name_suffix` - The part of the AZ name that appears after the region name, uniquely identifying the AZ within its region.
For Availability Zones this is usually a single letter, for example `a` for the `us-west-2a` zone.
For Local and Wavelength Zones this is a longer string, for example `wl1-sfo-wlz-1` for the `us-west-2-wl1-sfo-wlz-1` zone.
* `network_border_group` - The name of the location from which the address is advertised.
* `opt_in_status` - For Availability Zones, this always has the value of `opt-in-not-required`. For Local Zones, this is the opt in status. The possible values are `opted-in` and `not-opted-in`.
* `parent_zone_id` - The ID of the zone that handles some of the Local Zone or Wavelength Zone control plane operations, such as API calls.
* `parent_zone_name` - The name of the zone that handles some of the Local Zone or Wavelength Zone control plane operations, such as API calls.
* `region` - The region where the selected availability zone resides. This is always the region selected on the provider, since this data source searches only within that region.
* `zone_type` - The type of zone. Values are `availability-zone`, `local-zone`, and `wavelength-zone`.

0 comments on commit 896c7d3

Please sign in to comment.