Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 'google_billing_account' data source #889

Merged
merged 8 commits into from
Dec 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions google/data_source_google_billing_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package google

import (
"fmt"
"net/http"
"strings"

"github.com/hashicorp/terraform/helper/schema"

"google.golang.org/api/cloudbilling/v1"
"google.golang.org/api/googleapi"
)

func dataSourceGoogleBillingAccount() *schema.Resource {
return &schema.Resource{
Read: dataSourceBillingAccountRead,
Schema: map[string]*schema.Schema{
"billing_account": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"display_name"},
},
"display_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"billing_account"},
},
"open": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"project_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

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

open, openOk := d.GetOkExists("open")

var billingAccount *cloudbilling.BillingAccount
if v, ok := d.GetOk("billing_account"); ok {
resp, err := config.clientBilling.BillingAccounts.Get(canonicalBillingAccountName(v.(string))).Do()
if err != nil {
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == http.StatusNotFound {
return fmt.Errorf("Billing account not found: %s", v)
}

return fmt.Errorf("Error reading billing account: %s", err)
}

if openOk && resp.Open != open.(bool) {
return fmt.Errorf("Billing account not found: %s", v)
}

billingAccount = resp
} else if v, ok := d.GetOk("display_name"); ok {
token := ""
for paginate := true; paginate; {
resp, err := config.clientBilling.BillingAccounts.List().PageToken(token).Do()
if err != nil {
return fmt.Errorf("Error reading billing accounts: %s", err)
}

for _, ba := range resp.BillingAccounts {
if ba.DisplayName == v.(string) {
if openOk && ba.Open != open.(bool) {
continue
}
if billingAccount != nil {
return fmt.Errorf("More than one matching billing account found")
}
billingAccount = ba
}
}

token = resp.NextPageToken
paginate = token != ""
}

if billingAccount == nil {
return fmt.Errorf("Billing account not found: %s", v)
}
} else {
return fmt.Errorf("one of billing_account or display_name must be set")
}

resp, err := config.clientBilling.BillingAccounts.Projects.List(billingAccount.Name).Do()
if err != nil {
return fmt.Errorf("Error reading billing account projects: %s", err)
}
projectIds := flattenBillingProjects(resp.ProjectBillingInfo)

d.SetId(GetResourceNameFromSelfLink(billingAccount.Name))
d.Set("name", billingAccount.Name)
d.Set("display_name", billingAccount.DisplayName)
d.Set("open", billingAccount.Open)
d.Set("project_ids", projectIds)

return nil
}

func canonicalBillingAccountName(ba string) string {
if strings.HasPrefix(ba, "billingAccounts/") {
return ba
}

return "billingAccounts/" + ba
}

func flattenBillingProjects(billingProjects []*cloudbilling.ProjectBillingInfo) []string {
projectIds := make([]string, len(billingProjects))
for i, billingProject := range billingProjects {
projectIds[i] = billingProject.ProjectId
}

return projectIds
}
104 changes: 104 additions & 0 deletions google/data_source_google_billing_account_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package google

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform/helper/acctest"

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

func TestAccDataSourceGoogleBillingAccount_byFullName(t *testing.T) {
billingId := getTestBillingAccountFromEnv(t)
name := "billingAccounts/" + billingId

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckGoogleBillingAccount_byName(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.google_billing_account.acct", "id", billingId),
resource.TestCheckResourceAttr("data.google_billing_account.acct", "name", name),
resource.TestCheckResourceAttr("data.google_billing_account.acct", "open", "true"),
),
},
},
})
}

func TestAccDataSourceGoogleBillingAccount_byShortName(t *testing.T) {
billingId := getTestBillingAccountFromEnv(t)
name := "billingAccounts/" + billingId

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckGoogleBillingAccount_byName(billingId),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.google_billing_account.acct", "id", billingId),
resource.TestCheckResourceAttr("data.google_billing_account.acct", "name", name),
resource.TestCheckResourceAttr("data.google_billing_account.acct", "open", "true"),
),
},
},
})
}

func TestAccDataSourceGoogleBillingAccount_byFullNameClosed(t *testing.T) {
billingId := getTestBillingAccountFromEnv(t)
name := "billingAccounts/" + billingId

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckGoogleBillingAccount_byNameClosed(name),
ExpectError: regexp.MustCompile("Billing account not found: " + name),
},
},
})
}

func TestAccDataSourceGoogleBillingAccount_byDisplayName(t *testing.T) {
name := acctest.RandString(16)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckGoogleBillingAccount_byDisplayName(name),
ExpectError: regexp.MustCompile("Billing account not found: " + name),
},
},
})
}

func testAccCheckGoogleBillingAccount_byName(name string) string {
return fmt.Sprintf(`
data "google_billing_account" "acct" {
billing_account = "%s"
}`, name)
}

func testAccCheckGoogleBillingAccount_byNameClosed(name string) string {
return fmt.Sprintf(`
data "google_billing_account" "acct" {
billing_account = "%s"
open = false
}`, name)
}

func testAccCheckGoogleBillingAccount_byDisplayName(name string) string {
return fmt.Sprintf(`
data "google_billing_account" "acct" {
display_name = "%s"
}`, name)
}
1 change: 1 addition & 0 deletions google/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func Provider() terraform.ResourceProvider {
},

DataSourcesMap: map[string]*schema.Resource{
"google_billing_account": dataSourceGoogleBillingAccount(),
"google_dns_managed_zone": dataSourceDnsManagedZone(),
"google_client_config": dataSourceGoogleClientConfig(),
"google_compute_address": dataSourceGoogleComputeAddress(),
Expand Down
46 changes: 46 additions & 0 deletions website/docs/d/google_billing_account.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
layout: "google"
page_title: "Google: google_billing_account"
sidebar_current: "docs-google-datasource-billing-account"
description: |-
Get information about a Google Billing Account.
---

# google\_billing\_account

Use this data source to get information about a Google Billing Account.

```hcl
data "google_billing_account" "acct" {
display_name = "My Billing Account"
open = true
}

resource "google_project" "my_project" {
name = "My Project"
project_id = "your-project-id"
org_id = "1234567"

billing_account = "${data.google_billing_account.acct.id}"
}
```

## Argument Reference

The arguments of this data source act as filters for querying the available billing accounts.
The given filters must match exactly one billing account whose data will be exported as attributes.
The following arguments are supported:

* `billing_account` (Optional) - The name of the billing account in the form `{billing_account_id}` or `billingAccounts/{billing_account_id}`.
* `display_name` (Optional) - The display name of the billing account.
* `open` (Optional) - `true` if the billing account is open, `false` if the billing account is closed.

~> **NOTE:** One of `billing_account` or `display_name` must be specified.

## Attributes Reference

The following additional attributes are exported:

* `id` - The billing account ID.
* `name` - The resource name of the billing account in the form `billingAccounts/{billing_account_id}`.
* `project_ids` - The IDs of any projects associated with the billing account.
5 changes: 4 additions & 1 deletion website/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-billing-account") %>>
<a href="/docs/providers/google/d/google_billing_account.html">google_billing_account</a>
</li>
<li<%= sidebar_current("docs-google-datasource-client-config") %>>
<a href="/docs/providers/google/d/datasource_client_config.html">google_client_config</a>
</li>
Expand Down Expand Up @@ -136,7 +139,7 @@
</li>
<li<%= sidebar_current("docs-google-service-account") %>>
<a href="/docs/providers/google/r/google_service_account.html">google_service_account</a>
</li>
</li>
<li<%= sidebar_current("docs-google-service-account-iam") %>>
<a href="/docs/providers/google/r/google_service_account_iam.html">google_service_account_iam_binding</a>
</li>
Expand Down