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

providers/google: google_project supports billing account #11653

Merged
merged 5 commits into from
Feb 20, 2017

Conversation

evandbrown
Copy link
Contributor

This change allows a Terraform user to set and update the billing account associated with their project.

@evandbrown
Copy link
Contributor Author

This one is really tricky to write an integration test for. We'd need to create two dummy Billing Accounts in the testing Organization, and give the service account that runs the integration test the proper permission in the Organization. Then introduce the two Billing Account IDs as env vars to the tests. Not impossible, but really raises the bar for someone running the integration tests locally.

For now, I'm testing manually to verify create and update of a project with a billing account. Thoughts, @danawillow and @paddyforan?

Thanks!

Copy link
Contributor

@danawillow danawillow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a few nitpicks.

As for testing, I agree that it'll be tricky, especially for someone running locally (and I don't want another set of environment variables that have to be set for someone running it locally). If we had a way of using mocks (and then running non-mocks only via CI) that would probably be the ideal solution, but I don't see that happening anytime soon. For now my opinion is to just get the change in- I don't think that's too reckless (famous last words).

ba := cloudbilling.ProjectBillingInfo{
BillingAccountName: "billingAccounts/" + v.(string),
}
_, err = config.clientBilling.Projects.UpdateBillingInfo("projects/"+pid, &ba).Do()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: even though it's a teeny tiny thing, since you do "projects/" + pid a few times I wouldn't mind seeing that in a function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a nit at all! Done.

return fmt.Errorf("Error reading billing account for project %q: %v", "projects/"+pid, err)
}
if ba.BillingAccountName != "" {
_ba := strings.Split(ba.BillingAccountName, "billingAccounts/")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TrimPrefix is probably cleaner than split

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way this is written, I don't actually know what the string is expected to be... it could be any one of these:

Honestly, would love some clarification (esp as a code comment) around what ba.BillingAccountName is expected to be at this point. And agree strings.Split may not be the most semantic function to use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL TrimPrefix. Done.

@paddycarver
Copy link
Contributor

Have a few thoughts on this, let me circle around tomorrow. :)

Copy link
Contributor

@paddycarver paddycarver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, with just a few nitpicks here and there. For my part, though, I'd love to see some sort of tests here.

If I understand your explanation right, the problem is we would need to do some special setup on the project before we could run the tests, namely adding billing accounts, giving the service account permissions, and passing the billing accounts in as an environment variable.

My gut on this is that we've kind of crossed that bridge already:

  • XPN requires our project to be whitelisted before the tests can be run, anyways.
  • Projects requires the Org ID to be passed in as an environment variable.
  • Projects requires the service account to have specific permissions.

On my end, I think "untested features" is more frightening than "painful to test features", and at least with the painful to test features, we have good examples to look at when rethinking our testing framework, and can potentially make them simpler to run. There are some ways I can think of to automate the stuff we've mentioned so Terraform could bootstrap testing environments, and having "here's why that's a good idea" is always good.

That said, I'm open to being convinced that increasing the difficulty of running tests on non-official projects is not worth it in this case. My general stance is that making testing on non-official projects harder is bad, and we should avoid it where possible, but if it's necessary for us to test functionality, let's do it.

_, err = config.clientBilling.Projects.UpdateBillingInfo("projects/"+pid, &ba).Do()
if err != nil {
d.Set("billing_account", "")
if _err, ok := err.(*googleapi.Error); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a difference between how *googleapi.Error and error get printed when using %v?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is. The former will unpack and print any nested errors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough!

return fmt.Errorf("Error reading billing account for project %q: %v", "projects/"+pid, err)
}
if ba.BillingAccountName != "" {
_ba := strings.Split(ba.BillingAccountName, "billingAccounts/")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way this is written, I don't actually know what the string is expected to be... it could be any one of these:

Honestly, would love some clarification (esp as a code comment) around what ba.BillingAccountName is expected to be at this point. And agree strings.Split may not be the most semantic function to use.

@@ -210,6 +231,18 @@ func resourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error {
d.Set("policy_etag", pol.Etag)
d.Set("policy_data", string(polBytes))

// Read the billing account
ba, err := config.clientBilling.Projects.GetBillingInfo("projects/" + pid).Do()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like it's possible to create projects without a billing account (now), and this line of code is causing any projects which do not have a billing account to return a 403 on read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not seeing this. I've created a few projects (and just added tests that do the same) that don't have billing accounts but make it through read. GetBillingInfo should return an empty billing account if none is set. Possible to see your config?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evandbrown it's sadder than that 😦 . Steps to repro:

  1. Compile Terraform without this PR
  2. Create project
  3. Compile Terraform with this PR
  4. Change a project attr
  5. Get error

This change allows a Terraform user to set and update the billing
account associated with their project.
This change adds optional acceptance tests for project billing accounts.
GOOGLE_PROJECT_BILLING_ACCOUNT and GOOGLE_PROJECT_BILLING_ACCOUNT_2
must be set in the environment for the tests to run; otherwise, they
will be skipped.

Also includes a few code cleanups per review.
@evandbrown
Copy link
Contributor Author

@paddyforan totally reasonable; tests are added.

func testAccGoogleProject_createBilling(pid, name, org, billing string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like tabs vs spaces happened here

@paddycarver
Copy link
Contributor

Thanks for adding those tests, @evandbrown! This looks great. Looks like @sethvargo had a nit about tabs/spaces, don't know if you want to update that or not. Either is fine by me. But this has a 👍 from me.

@stack72 stack72 merged commit facc50d into hashicorp:master Feb 20, 2017
stack72 pushed a commit that referenced this pull request Feb 20, 2017
* Vendor google.golang.org/api/cloudbilling/v1

* providers/google: Add cloudbilling client

* providers/google: google_project supports billing account

This change allows a Terraform user to set and update the billing
account associated with their project.

* providers/google: Testing project billing account

This change adds optional acceptance tests for project billing accounts.
GOOGLE_PROJECT_BILLING_ACCOUNT and GOOGLE_PROJECT_BILLING_ACCOUNT_2
must be set in the environment for the tests to run; otherwise, they
will be skipped.

Also includes a few code cleanups per review.

* providers/google: Improve project billing error message
@ghost
Copy link

ghost commented Apr 16, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants