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: Create and delete Service Accounts #9946

Merged

Conversation

evandbrown
Copy link
Contributor

@evandbrown evandbrown commented Nov 8, 2016

This change adds support for the google_service_account resource. The google_service_account allows a Terraform user to create, modify, and delete Service Accounts on Google Cloud Platform.

@evandbrown
Copy link
Contributor Author

evandbrown commented Nov 8, 2016

Ping @danawillow for super-early initial review. Tomorrow I'll add docs and support for IAM policy attachment.

@cblecker
Copy link
Contributor

cblecker commented Nov 8, 2016

This is awesome! I actually went looking to see if Terraform could do this just the other day.

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.

Looks fine overall, just a few small things.

sa, err := config.clientIAM.Projects.ServiceAccounts.Get(d.Id()).Do()
if err != nil {
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
log.Printf("[WARN] Removing service account %q because it no longer exists", d.Id())
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like if I saw this error message when running a command I would have no idea what it meant. Maybe something like "resetting reference to" instead of "removing"? Not sure I love that either honestly. What exactly is happening here?

return fmt.Errorf("Error getting service account with name %q: %s", d.Id(), err)
}

return fmt.Errorf("Error reading service account: %q", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does the above error message reference the name and not this one?

var testAccGoogleServiceAccount_basic = `
resource "google_service_account" "acceptance" {
account_id = "%v"
display_name = "%v"
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: alignment


var testAccGoogleServiceAccount_basic = `
resource "google_service_account" "acceptance" {
account_id = "%v"
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of passing static variables, would it not be preferable to have a test that passes a random character string, similar to the other google provider tests (example:

resource "google_compute_route" "foobar" {
name = "route-test-%s"
dest_range = "15.0.0.0/24"
network = "${google_compute_network.foobar.name}"
next_hop_ip = "10.0.1.5"
priority = 100
}`, acctest.RandString(10), acctest.RandString(10))
)

This would ensure a test wouldn't falsely pass because a resource wasn't cleaned up matching the static name. Or is there some reason I'm missing that wouldn't work for this resource type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I initially had some concerns about a circular reference between service accounts and IAM policies. Still working through that, but I'll use the random char where possible. Thanks!

@evandbrown evandbrown force-pushed the google-service-account-resource branch from 3f260aa to 5423349 Compare November 14, 2016 04:49
@evandbrown evandbrown changed the title WIP: providers/google: Create and delete Service Accounts providers/google: Create and delete Service Accounts Nov 14, 2016
@evandbrown evandbrown self-assigned this Nov 14, 2016
@evandbrown
Copy link
Contributor Author

@cblecker You want to make the call on merging this? Makes sense to me as you're interested in the feature :)

Copy link
Contributor

@cblecker cblecker left a comment

Choose a reason for hiding this comment

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

As far as I can see, the code looks good. Do the acceptance tests all pass? I'm still in the learning stages of Go, though. A few alignment and spacing nits.

I'll let someone else make the call on merging though, both because I'm inexperienced, and I don't have merge rights :P

@@ -24,6 +24,9 @@
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-google-project") %>>
<a href="/docs/providers/google/r/google_project.html">google_project</a>
</li>
<li<%= sidebar_current("docs-google-service-account") %>>
<a href="/docs/providers/google/r/google_service_account.html">google_service_account</a>
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: alignment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Gah tabs v spaces in vim. Thanks!

var testAccGoogleServiceAccount_policy = `
resource "google_service_account" "acceptance" {
account_id = "%v"
display_name = "%v"
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: alignment


Changing this updates the policy.

Deleting this removes the policy, but leaves the original policy
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: double space after original

```js
resource "google_service_account" "object_viewer" {
account_id = "object-viewer"
display_name = "Object viewer"
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: alignment

@evandbrown
Copy link
Contributor Author

Thanks, @cblecker! Acceptance tests are good:

$ make testacc TEST=./builtin/providers/google GOOGLE_PROJECT=evandbrown17 GOOGLE_REGION=us-central1 TESTARGS='-run=TestAccGoogleServiceAccount_...'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2016/11/14 11:18:48 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/google -v -run=TestAccGoogleServiceAccount_... -timeout 120m
=== RUN   TestAccGoogleServiceAccount_basic
--- PASS: TestAccGoogleServiceAccount_basic (5.84s)
=== RUN   TestAccGoogleServiceAccount_createPolicy
--- PASS: TestAccGoogleServiceAccount_createPolicy (7.74s)
PASS
ok      github.com/hashicorp/terraform/builtin/providers/google 13.645s

$ git rev-parse HEAD
4bdf65c36f7dd2092692d6e311845050b08add99

I know Mr @stack72 had need for service accounts recently. Perhaps he'd like to comment on this change and merge when ready?

@paddycarver
Copy link
Contributor

If @stack72 doesn't get a chance this week to make the call, I will. :)

@paddycarver paddycarver self-assigned this Nov 15, 2016
@paddycarver
Copy link
Contributor

@stack72 passed this to me, so I'll have a response for it in the next few days. :)

}

oldPStringf, _ := json.MarshalIndent(oldPString, "", " ")
newPStringf, _ := json.MarshalIndent(newPString, "", " ")
Copy link
Contributor

Choose a reason for hiding this comment

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

Why use json.MarshalIndent here? It's being called on a string, so from my experiments, it would seem to have no effect that fmt.Printf("%q") wouldn't. Also, ignoring the errors is making me nervous. I understand that it'll only effect debug outputs, but even just logging them and carrying on would make me feel better; at least we would have accurate debug output. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ooh, %q. That works!

Steps: []resource.TestStep{
// The first step creates a basic service account
resource.TestStep{
Config: fmt.Sprintf(testAccGoogleServiceAccount_basic, accountId, displayName),
Copy link
Contributor

Choose a reason for hiding this comment

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

The pattern I've seen is that these get implemented as functions, with accountId and displayName passed in as arguments and the Config string returned, instead of as fmt.Sprintf strings. This seems like a better option to me, as it documents the requirements and should they change after this is reused, it won't build unless you update them everywhere. With the Sprintf string, it'll just have weird output.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great catch. Fixed.

return fmt.Errorf("Not found: %s", r)
}

if rs.Primary.Attributes["display_name"] != displayName2 {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm probably missing something basic here, but why make displayName2 global mutable state instead of passing it in as an argument, as you did for testAccCheckGoogleServiceAccountPolicyCount?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're not missing anything; I missed that in a refactor.


# google\_service\_account

Allows management of a Google Cloud Platform service account.
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe link to service account docs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Changing this updates the policy.

Deleting this removes the policy, but leaves the original policy
intact. If there are overlapping `binding` entries between the original
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the "original policy" in this case? I'm somewhat familiar with service accounts, but I'm confused about what happens when deleting the policy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Clarified.

@paddycarver
Copy link
Contributor

Sorry for the delay. Got around to reviewing this, and I had a few questions. They may not require code changes at all, it's entirely possible I'm missing things. :) Let me know if you have any questions or disagree with any of my feedback. And thanks for taking the time to submit the new resource!

@evandbrown
Copy link
Contributor Author

Thanks, @paddyforan. Great feedback, and prompt. I really appreciate it. Just pushed a new change that addresses them all.

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.

Thanks for the speedy update on the code. Glad the review was helpful.

This looks good to me, so I'll go ahead and merge it. Super glad we got this in, and thanks again for contributing it!

intact. If there are overlapping `binding` entries between the original
policy and the data source policy, they will be removed.
Deleting this removes the policy declared in Terraform. Any policy bindings
associated with the project before Terraform was used are not deleted.
Copy link
Contributor

Choose a reason for hiding this comment

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

That makes so much more sense to me now. :D

@paddycarver paddycarver merged commit 642dd87 into hashicorp:master Nov 17, 2016
@ghost
Copy link

ghost commented Apr 20, 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 20, 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.

4 participants