Skip to content

Commit c8785cd

Browse files
committed
Merge pull request hashicorp#11954 from hashicorp/f-google-compute-zones
provider/google: Add google_compute_zones data source
1 parent a8d39f4 commit c8785cd

5 files changed

Lines changed: 195 additions & 1 deletion

File tree

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package google
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"sort"
7+
"time"
8+
9+
"github.com/hashicorp/terraform/helper/schema"
10+
compute "google.golang.org/api/compute/v1"
11+
)
12+
13+
func dataSourceGoogleComputeZones() *schema.Resource {
14+
return &schema.Resource{
15+
Read: dataSourceGoogleComputeZonesRead,
16+
Schema: map[string]*schema.Schema{
17+
"region": {
18+
Type: schema.TypeString,
19+
Optional: true,
20+
},
21+
"names": {
22+
Type: schema.TypeList,
23+
Computed: true,
24+
Elem: &schema.Schema{Type: schema.TypeString},
25+
},
26+
"status": {
27+
Type: schema.TypeString,
28+
Optional: true,
29+
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
30+
value := v.(string)
31+
if value != "UP" && value != "DOWN" {
32+
es = append(es, fmt.Errorf("%q can only be 'UP' or 'DOWN' (%q given)", k, value))
33+
}
34+
return
35+
},
36+
},
37+
},
38+
}
39+
}
40+
41+
func dataSourceGoogleComputeZonesRead(d *schema.ResourceData, meta interface{}) error {
42+
config := meta.(*Config)
43+
44+
region := config.Region
45+
if r, ok := d.GetOk("region"); ok {
46+
region = r.(string)
47+
}
48+
49+
regionUrl := fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/regions/%s",
50+
config.Project, region)
51+
filter := fmt.Sprintf("(region eq %s)", regionUrl)
52+
53+
if s, ok := d.GetOk("status"); ok {
54+
filter += fmt.Sprintf(" (status eq %s)", s)
55+
}
56+
57+
call := config.clientCompute.Zones.List(config.Project).Filter(filter)
58+
59+
resp, err := call.Do()
60+
if err != nil {
61+
return err
62+
}
63+
64+
zones := flattenZones(resp.Items)
65+
log.Printf("[DEBUG] Received Google Compute Zones: %q", zones)
66+
67+
d.Set("names", zones)
68+
d.SetId(time.Now().UTC().String())
69+
70+
return nil
71+
}
72+
73+
func flattenZones(zones []*compute.Zone) []string {
74+
result := make([]string, len(zones), len(zones))
75+
for i, zone := range zones {
76+
result[i] = zone.Name
77+
}
78+
sort.Strings(result)
79+
return result
80+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package google
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform/helper/resource"
10+
"github.com/hashicorp/terraform/terraform"
11+
)
12+
13+
func TestAccGoogleComputeZones_basic(t *testing.T) {
14+
resource.Test(t, resource.TestCase{
15+
PreCheck: func() { testAccPreCheck(t) },
16+
Providers: testAccProviders,
17+
Steps: []resource.TestStep{
18+
{
19+
Config: testAccCheckGoogleComputeZonesConfig,
20+
Check: resource.ComposeTestCheckFunc(
21+
testAccCheckGoogleComputeZonesMeta("data.google_compute_zones.available"),
22+
),
23+
},
24+
},
25+
})
26+
}
27+
28+
func testAccCheckGoogleComputeZonesMeta(n string) resource.TestCheckFunc {
29+
return func(s *terraform.State) error {
30+
rs, ok := s.RootModule().Resources[n]
31+
if !ok {
32+
return fmt.Errorf("Can't find zones data source: %s", n)
33+
}
34+
35+
if rs.Primary.ID == "" {
36+
return errors.New("zones data source ID not set.")
37+
}
38+
39+
count, ok := rs.Primary.Attributes["names.#"]
40+
if !ok {
41+
return errors.New("can't find 'names' attribute")
42+
}
43+
44+
noOfNames, err := strconv.Atoi(count)
45+
if err != nil {
46+
return errors.New("failed to read number of zones")
47+
}
48+
if noOfNames < 2 {
49+
return fmt.Errorf("expected at least 2 zones, received %d, this is most likely a bug",
50+
noOfNames)
51+
}
52+
53+
for i := 0; i < noOfNames; i++ {
54+
idx := "names." + strconv.Itoa(i)
55+
v, ok := rs.Primary.Attributes[idx]
56+
if !ok {
57+
return fmt.Errorf("zone list is corrupt (%q not found), this is definitely a bug", idx)
58+
}
59+
if len(v) < 1 {
60+
return fmt.Errorf("Empty zone name (%q), this is definitely a bug", idx)
61+
}
62+
}
63+
64+
return nil
65+
}
66+
}
67+
68+
var testAccCheckGoogleComputeZonesConfig = `
69+
data "google_compute_zones" "available" {}
70+
`

‎builtin/providers/google/provider.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ func Provider() terraform.ResourceProvider {
5757
},
5858

5959
DataSourcesMap: map[string]*schema.Resource{
60-
"google_iam_policy": dataSourceGoogleIamPolicy(),
60+
"google_iam_policy": dataSourceGoogleIamPolicy(),
61+
"google_compute_zones": dataSourceGoogleComputeZones(),
6162
},
6263

6364
ResourcesMap: map[string]*schema.Resource{
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
layout: "google"
3+
page_title: "Google: google_compute_zones"
4+
sidebar_current: "docs-google-datasource-compute-zones"
5+
description: |-
6+
Provides a list of available Google Compute zones
7+
---
8+
9+
# google\_compute\_zones
10+
11+
Provides access to available Google Compute zones in a region for a given project.
12+
See more about [regions and zones](https://cloud.google.com/compute/docs/regions-zones/regions-zones) in the upstream docs.
13+
14+
```
15+
data "google_compute_zones" "available" {}
16+
17+
resource "google_compute_instance_group_manager" "foo" {
18+
count = "${length(data.google_compute_zones.available.names)}"
19+
20+
name = "terraform-test-${count.index}"
21+
instance_template = "${google_compute_instance_template.foobar.self_link}"
22+
base_instance_name = "foobar-${count.index}"
23+
zone = "${data.google_compute_zones.available.names[count.index]}"
24+
target_size = 1
25+
}
26+
```
27+
28+
## Argument Reference
29+
30+
The following arguments are supported:
31+
32+
* `region` (Optional) - Region from which to list available zones. Defaults to region declared in the provider.
33+
* `status` (Optional) - Allows to filter list of zones based on their current status. Status can be either `UP` or `DOWN`.
34+
Defaults to no filtering (all available zones - both `UP` and `DOWN`).
35+
36+
## Attributes Reference
37+
38+
The following attribute is exported:
39+
40+
* `names` - A list of zones available in the given region

‎website/source/layouts/google.erb‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
<li<%= sidebar_current(/^docs-google-datasource/) %>>
1414
<a href="#">Google Cloud Platform Data Sources</a>
1515
<ul class="nav nav-visible">
16+
<li<%= sidebar_current("docs-google-datasource-compute-zones") %>>
17+
<a href="/docs/providers/google/d/google_compute_zones.html">google_compute_zones</a>
18+
</li>
1619
<li<%= sidebar_current("docs-google-datasource-iam-policy") %>>
1720
<a href="/docs/providers/google/d/google_iam_policy.html">google_iam_policy</a>
1821
</li>

0 commit comments

Comments
 (0)