From 5e5cc2eeaca012958af0bf02759e8731e42498bc Mon Sep 17 00:00:00 2001 From: jaime Bernabe <6184069+Monitob@users.noreply.github.com> Date: Mon, 24 Apr 2023 16:12:52 +0200 Subject: [PATCH 1/2] feat(availability_zone): add data source availability zone --- docs/data-sources/availability_zone.md | 31 +++++++++++ scaleway/data_source_availability_zone.go | 53 +++++++++++++++++++ .../data_source_availability_zone_test.go | 46 ++++++++++++++++ scaleway/helpers.go | 52 ++++++++++++++++++ scaleway/provider.go | 1 + 5 files changed, 183 insertions(+) create mode 100644 docs/data-sources/availability_zone.md create mode 100644 scaleway/data_source_availability_zone.go create mode 100644 scaleway/data_source_availability_zone_test.go diff --git a/docs/data-sources/availability_zone.md b/docs/data-sources/availability_zone.md new file mode 100644 index 0000000000..6ff9a6e8e0 --- /dev/null +++ b/docs/data-sources/availability_zone.md @@ -0,0 +1,31 @@ +--- +subcategory: "Account" +page_title: "Scaleway: scaleway_availability_zone" +--- + +# scaleway_availability_zone + +Use this data source to get the available zones information based on its Region. + +For technical and legal reasons, some products are split by Region or by Availability Zones. When using such product, +you can choose the location that better fits your need (country, latency, …). + +## Example Usage + +```hcl +# Get info by Region key +data scaleway_availability_zone main { + region = "nl-ams" +} +``` + +## Argument Reference + +- `region` - Region is represented as a Geographical area such as France. Defaults: `fr-par`. + +## Attributes Reference + +In addition to all above arguments, the following attributes are exported: + +- `id` - The Region ID +- `zones` - List of availability zones by regions diff --git a/scaleway/data_source_availability_zone.go b/scaleway/data_source_availability_zone.go new file mode 100644 index 0000000000..926e8f389e --- /dev/null +++ b/scaleway/data_source_availability_zone.go @@ -0,0 +1,53 @@ +package scaleway + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/scaleway/scaleway-sdk-go/scw" + "github.com/scaleway/scaleway-sdk-go/validation" +) + +func DataSourceAvailabilityZone() *schema.Resource { + return &schema.Resource{ + ReadWithoutTimeout: dataSourceAvailabilityZoneRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "region": { + Type: schema.TypeString, + Optional: true, + Description: "Region is represented as a Geographical area such as France", + Default: scw.RegionFrPar, + }, + "zones": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Computed: true, + Description: "Availability Zones (AZ)", + }, + }, + } +} + +func dataSourceAvailabilityZoneRead(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + regionStr := d.Get("region").(string) + + if !validation.IsRegion(regionStr) { + return diag.FromErr(SingularDataSourceFindError("Availability Zone", fmt.Errorf("not a supported region %s", regionStr))) + } + + region := scw.Region(regionStr) + d.SetId(regionStr) + _ = d.Set("zones", region.GetZones()) + + return nil +} diff --git a/scaleway/data_source_availability_zone_test.go b/scaleway/data_source_availability_zone_test.go new file mode 100644 index 0000000000..d85d7b06c0 --- /dev/null +++ b/scaleway/data_source_availability_zone_test.go @@ -0,0 +1,46 @@ +package scaleway + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccScalewayDataSourceAvailabilityZone_Basic(t *testing.T) { + tt := NewTestTools(t) + defer tt.Cleanup() + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: tt.ProviderFactories, + CheckDestroy: testAccCheckScalewayDomainRecordDestroy(tt), + Steps: []resource.TestStep{ + { + Config: ` + data scaleway_availability_zone main { + } + `, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.scaleway_availability_zone.main", "region", "fr-par"), + resource.TestCheckResourceAttr( + "data.scaleway_availability_zone.main", "zones.0", "fr-par-1"), + ), + }, + { + Config: ` + data scaleway_availability_zone main { + region = "nl-ams" + } + `, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.scaleway_availability_zone.main", "region", "nl-ams"), + resource.TestCheckResourceAttr( + "data.scaleway_availability_zone.main", "zones.0", "nl-ams-1"), + resource.TestCheckResourceAttr( + "data.scaleway_availability_zone.main", "zones.1", "nl-ams-2"), + ), + }, + }, + }) +} diff --git a/scaleway/helpers.go b/scaleway/helpers.go index e903ad3433..1452b4b3fa 100644 --- a/scaleway/helpers.go +++ b/scaleway/helpers.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/scaleway/scaleway-sdk-go/namegenerator" @@ -954,3 +955,54 @@ func customizeDiffLocalityCheck(keys ...string) schema.CustomizeDiffFunc { return nil } } + +type TooManyResultsError struct { + Count int + LastRequest interface{} +} + +func (e *TooManyResultsError) Error() string { + return fmt.Sprintf("too many results: wanted 1, got %d", e.Count) +} + +func (e *TooManyResultsError) Is(err error) bool { + _, ok := err.(*TooManyResultsError) //nolint:errorlint // Explicitly does *not* match down the error tree + return ok +} + +func (e *TooManyResultsError) As(target interface{}) bool { + t, ok := target.(**retry.NotFoundError) + if !ok { + return false + } + + *t = &retry.NotFoundError{ + Message: e.Error(), + LastRequest: e.LastRequest, + } + + return true +} + +var ErrTooManyResults = &TooManyResultsError{} + +// SingularDataSourceFindError returns a standard error message for a singular data source's non-nil resource find error. +func SingularDataSourceFindError(resourceType string, err error) error { + if NotFound(err) { + if errors.Is(err, &TooManyResultsError{}) { + return fmt.Errorf("multiple %[1]ss matched; use additional constraints to reduce matches to a single %[1]s", resourceType) + } + + return fmt.Errorf("no matching %[1]s found", resourceType) + } + + return fmt.Errorf("reading %s: %w", resourceType, err) +} + +// NotFound returns true if the error represents a "resource not found" condition. +// Specifically, NotFound returns true if the error or a wrapped error is of type +// retry.NotFoundError. +func NotFound(err error) bool { + var e *retry.NotFoundError // nosemgrep:ci.is-not-found-error + return errors.As(err, &e) +} diff --git a/scaleway/provider.go b/scaleway/provider.go index 5aa06bd11f..e820b24d75 100644 --- a/scaleway/provider.go +++ b/scaleway/provider.go @@ -165,6 +165,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc { DataSourcesMap: map[string]*schema.Resource{ "scaleway_account_project": dataSourceScalewayAccountProject(), "scaleway_account_ssh_key": dataSourceScalewayAccountSSHKey(), + "scaleway_availability_zone": DataSourceAvailabilityZone(), "scaleway_baremetal_offer": dataSourceScalewayBaremetalOffer(), "scaleway_baremetal_option": dataSourceScalewayBaremetalOption(), "scaleway_baremetal_os": dataSourceScalewayBaremetalOs(), From 162a60756b09a33628a143a78a3e4286382f878e Mon Sep 17 00:00:00 2001 From: jaime Bernabe <6184069+Monitob@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:04:35 +0200 Subject: [PATCH 2/2] fix(availability_zones): rename resource --- ...vailability_zone.md => availability_zones.md} | 6 +++--- ...zone.go => data_source_availability_zones.go} | 6 +++--- ...go => data_source_availability_zones_test.go} | 16 ++++++++-------- scaleway/provider.go | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) rename docs/data-sources/{availability_zone.md => availability_zones.md} (84%) rename scaleway/{data_source_availability_zone.go => data_source_availability_zones.go} (83%) rename scaleway/{data_source_availability_zone_test.go => data_source_availability_zones_test.go} (60%) diff --git a/docs/data-sources/availability_zone.md b/docs/data-sources/availability_zones.md similarity index 84% rename from docs/data-sources/availability_zone.md rename to docs/data-sources/availability_zones.md index 6ff9a6e8e0..e1f17269ec 100644 --- a/docs/data-sources/availability_zone.md +++ b/docs/data-sources/availability_zones.md @@ -1,9 +1,9 @@ --- subcategory: "Account" -page_title: "Scaleway: scaleway_availability_zone" +page_title: "Scaleway: scaleway_availability_zones" --- -# scaleway_availability_zone +# scaleway_availability_zones Use this data source to get the available zones information based on its Region. @@ -14,7 +14,7 @@ you can choose the location that better fits your need (country, latency, …). ```hcl # Get info by Region key -data scaleway_availability_zone main { +data scaleway_availability_zones main { region = "nl-ams" } ``` diff --git a/scaleway/data_source_availability_zone.go b/scaleway/data_source_availability_zones.go similarity index 83% rename from scaleway/data_source_availability_zone.go rename to scaleway/data_source_availability_zones.go index 926e8f389e..446adf15c8 100644 --- a/scaleway/data_source_availability_zone.go +++ b/scaleway/data_source_availability_zones.go @@ -11,9 +11,9 @@ import ( "github.com/scaleway/scaleway-sdk-go/validation" ) -func DataSourceAvailabilityZone() *schema.Resource { +func DataSourceAvailabilityZones() *schema.Resource { return &schema.Resource{ - ReadWithoutTimeout: dataSourceAvailabilityZoneRead, + ReadWithoutTimeout: dataSourceAvailabilityZonesRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(20 * time.Minute), @@ -38,7 +38,7 @@ func DataSourceAvailabilityZone() *schema.Resource { } } -func dataSourceAvailabilityZoneRead(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { +func dataSourceAvailabilityZonesRead(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { regionStr := d.Get("region").(string) if !validation.IsRegion(regionStr) { diff --git a/scaleway/data_source_availability_zone_test.go b/scaleway/data_source_availability_zones_test.go similarity index 60% rename from scaleway/data_source_availability_zone_test.go rename to scaleway/data_source_availability_zones_test.go index d85d7b06c0..4928033975 100644 --- a/scaleway/data_source_availability_zone_test.go +++ b/scaleway/data_source_availability_zones_test.go @@ -6,7 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) -func TestAccScalewayDataSourceAvailabilityZone_Basic(t *testing.T) { +func TestAccScalewayDataSourceAvailabilityZones_Basic(t *testing.T) { tt := NewTestTools(t) defer tt.Cleanup() resource.ParallelTest(t, resource.TestCase{ @@ -16,29 +16,29 @@ func TestAccScalewayDataSourceAvailabilityZone_Basic(t *testing.T) { Steps: []resource.TestStep{ { Config: ` - data scaleway_availability_zone main { + data scaleway_availability_zones main { } `, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "data.scaleway_availability_zone.main", "region", "fr-par"), + "data.scaleway_availability_zones.main", "region", "fr-par"), resource.TestCheckResourceAttr( - "data.scaleway_availability_zone.main", "zones.0", "fr-par-1"), + "data.scaleway_availability_zones.main", "zones.0", "fr-par-1"), ), }, { Config: ` - data scaleway_availability_zone main { + data scaleway_availability_zones main { region = "nl-ams" } `, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "data.scaleway_availability_zone.main", "region", "nl-ams"), + "data.scaleway_availability_zones.main", "region", "nl-ams"), resource.TestCheckResourceAttr( - "data.scaleway_availability_zone.main", "zones.0", "nl-ams-1"), + "data.scaleway_availability_zones.main", "zones.0", "nl-ams-1"), resource.TestCheckResourceAttr( - "data.scaleway_availability_zone.main", "zones.1", "nl-ams-2"), + "data.scaleway_availability_zones.main", "zones.1", "nl-ams-2"), ), }, }, diff --git a/scaleway/provider.go b/scaleway/provider.go index e820b24d75..2dc71537a6 100644 --- a/scaleway/provider.go +++ b/scaleway/provider.go @@ -165,7 +165,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc { DataSourcesMap: map[string]*schema.Resource{ "scaleway_account_project": dataSourceScalewayAccountProject(), "scaleway_account_ssh_key": dataSourceScalewayAccountSSHKey(), - "scaleway_availability_zone": DataSourceAvailabilityZone(), + "scaleway_availability_zones": DataSourceAvailabilityZones(), "scaleway_baremetal_offer": dataSourceScalewayBaremetalOffer(), "scaleway_baremetal_option": dataSourceScalewayBaremetalOption(), "scaleway_baremetal_os": dataSourceScalewayBaremetalOs(),