Skip to content

Commit

Permalink
provider/google: Add google_compute_zones data source
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Feb 15, 2017
1 parent 235b7eb commit c40b0de
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 1 deletion.
80 changes: 80 additions & 0 deletions builtin/providers/google/data_source_google_compute_zones.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package google

import (
"fmt"
"log"
"sort"
"time"

"github.com/hashicorp/terraform/helper/schema"
compute "google.golang.org/api/compute/v1"
)

func dataSourceGoogleComputeZones() *schema.Resource {
return &schema.Resource{
Read: dataSourceGoogleComputeZonesRead,
Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Optional: true,
},
"names": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"status": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
value := v.(string)
if value != "UP" && value != "DOWN" {
es = append(es, fmt.Errorf("%q can only be 'UP' or 'DOWN' (%q given)", k, value))
}
return
},
},
},
}
}

func dataSourceGoogleComputeZonesRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

region := config.Region
if r, ok := d.GetOk("region"); ok {
region = r.(string)
}

regionUrl := fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/regions/%s",
config.Project, region)
filter := fmt.Sprintf("(region eq %s)", regionUrl)

if s, ok := d.GetOk("status"); ok {
filter += fmt.Sprintf(" (status eq %s)", s)
}

call := config.clientCompute.Zones.List(config.Project).Filter(filter)

resp, err := call.Do()
if err != nil {
return err
}

zones := flattenZones(resp.Items)
log.Printf("[DEBUG] Received Google Compute Zones: %q", zones)

d.Set("names", zones)
d.SetId(time.Now().UTC().String())

return nil
}

func flattenZones(zones []*compute.Zone) []string {
result := make([]string, len(zones), len(zones))
for i, zone := range zones {
result[i] = zone.Name
}
sort.Strings(result)
return result
}
70 changes: 70 additions & 0 deletions builtin/providers/google/data_source_google_compute_zones_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package google

import (
"errors"
"fmt"
"strconv"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccGoogleComputeZones_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckGoogleComputeZonesConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleComputeZonesMeta("data.google_compute_zones.available"),
),
},
},
})
}

func testAccCheckGoogleComputeZonesMeta(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Can't find zones data source: %s", n)
}

if rs.Primary.ID == "" {
return errors.New("zones data source ID not set.")
}

count, ok := rs.Primary.Attributes["names.#"]
if !ok {
return errors.New("can't find 'names' attribute")
}

noOfNames, err := strconv.Atoi(count)
if err != nil {
return errors.New("failed to read number of zones")
}
if noOfNames < 2 {
return fmt.Errorf("expected at least %d zones, received %d, this is most likely a bug",
noOfNames, noOfNames)
}

for i := 0; i < noOfNames; i++ {
idx := "names." + strconv.Itoa(i)
v, ok := rs.Primary.Attributes[idx]
if !ok {
return fmt.Errorf("zone list is corrupt (%q not found), this is definitely a bug", idx)
}
if len(v) < 1 {
return fmt.Errorf("Empty zone name (%q), this is definitely a bug", idx)
}
}

return nil
}
}

var testAccCheckGoogleComputeZonesConfig = `
data "google_compute_zones" "available" {}
`
3 changes: 2 additions & 1 deletion builtin/providers/google/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ func Provider() terraform.ResourceProvider {
},

DataSourcesMap: map[string]*schema.Resource{
"google_iam_policy": dataSourceGoogleIamPolicy(),
"google_iam_policy": dataSourceGoogleIamPolicy(),
"google_compute_zones": dataSourceGoogleComputeZones(),
},

ResourcesMap: map[string]*schema.Resource{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
layout: "google"
page_title: "Google: google_compute_zones"
sidebar_current: "docs-google-datasource-compute-zones"
description: |-
Provides a list of available Google Compute zones
---

# google\_compute\_zones

Provides access to available Google Compute zones in a region for a given project.
See more about [regions and zones](https://cloud.google.com/compute/docs/regions-zones/regions-zones) in the upstream docs.

```
data "google_compute_zones" "available" {}
resource "google_compute_instance_group_manager" "foo" {
count = "${length(data.google_compute_zones.available.names)}"
name = "terraform-test-${count.index}"
instance_template = "${google_compute_instance_template.foobar.self_link}"
base_instance_name = "foobar-${count.index}"
zone = "${data.google_compute_zones.available.names[count.index]}"
target_size = 1
}
```

## Argument Reference

The following arguments are supported:

* `region` (Optional) - Region from which to list available zones. Defaults to region declared in the provider.
* `status` (Optional) - Allows to filter list of zones based on their current status. Status can be either `UP` or `DOWN`.
Defaults to no filtering (all available zones - both `UP` and `DOWN`).

## Attributes Reference

The following attribute is exported:

* `names` - A list of zones available in the given region
3 changes: 3 additions & 0 deletions website/source/layouts/google.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
<li<%= sidebar_current(/^docs-google-datasource/) %>>
<a href="#">Google Cloud Platform Data Sources</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-google-datasource-compute-zones") %>>
<a href="/docs/providers/google/d/google_compute_zones.html">google_compute_zones</a>
</li>
<li<%= sidebar_current("docs-google-datasource-iam-policy") %>>
<a href="/docs/providers/google/d/google_iam_policy.html">google_iam_policy</a>
</li>
Expand Down

0 comments on commit c40b0de

Please sign in to comment.