Skip to content
This repository has been archived by the owner on Jun 27, 2021. It is now read-only.

remove update from creation #120

Merged
merged 1 commit into from
Jan 17, 2020
Merged

Conversation

joshua-rutherford
Copy link
Contributor

@DeviaVir, fairly straight forward change to prevent the same user getting imported as multiple terraform resources by accident. This does change the behavior on initial creations (i.e., no longer imports so you'll have to explicitly import existing users).

@DeviaVir
Copy link
Owner

DeviaVir commented Jan 9, 2020

@joshua-rutherford apologies for what may seem like a silly thing (I have not looked at this side of the code for a little while). The idea iirc is that if the user already exists we update the existing user. It should not be importing a new resource, just update an existing user. I do want the provider to be authoritative meaning that if you define a user and it already exists terraform shouldn't error out, but instead overwrite existing values. Perhaps there's a better way to do this..?

@joshua-rutherford
Copy link
Contributor Author

joshua-rutherford commented Jan 10, 2020

Normally if you wish to bring an existing entity in the remote system under configuration control as a terraform resource you must terraform import RESOURCE ID the entity first. Once you've imported the entity as a resource, the next run of terraform apply will make the remote entity match the state in terraform (i.e., terraform is authoritative).

Your resource already supports the import method (I used it to import my entire GSuite account base quite quickly) so I see this feature on creation as redundant. One other benefit to the explicit import syntax is that import only makes the state in terraform match that in the remote. So if I define an empty user resource like:

resource "gsuite_user" "chester_copperpot" {}

And import it with the following:

terraform import gsuite_user.chester_copperpot [email protected]

The next time I run terraform plan the plan will actually show me what the current state of the GSuite user is and what it will change to so I can update my resource definition before applying. This was exceptionally helpful because while I as an administrator can be authoritative on my my user's names, e-mails and aliases, I don't actually know a single one of their recovery email addresses or phone numbers. So I defined all my resources without those, imported and planned and knew what addresses and phone numbers were going to be overwritten with blanks if I didn't add them.

Now that I have their accounts defined in a terraform module I can check it into the git repo and allow them to make changes there with my approval because they should be able to reset the recovery email but not their email address.

I have to admit the idea that create would also import is intriguing but not really a pattern I've ever seen in terraform.

@DeviaVir
Copy link
Owner

DeviaVir commented Jan 10, 2020

I understand from the viewpoint of import, but if you do not do an import first you end up with the provider not becoming authoritative, meaning that if you have users today and you define them in terraform without importing, the provider would have to return an "already exists error".

The pattern of the provider being more authoritative and returning less errors is fairly new but one that is becoming more and more prevalent.

I think if the issue here is that we somehow end up with multiple resources managing the same primary_email, that should be (made) impossible- I'm not sure how removing the read and update for existing resources (i.e. import and overwrite existing on create) helps with this?

@joshua-rutherford
Copy link
Contributor Author

I'm really just trying to prevent myself from locking existing users out of their account and provide enough feed back to administrators that they've got a bad configuration defined. Like I said, you already have support for import so I guess I can make do with out this but the cost of always assuming that terraform is right is that you always assume administrators are correct in the way they define their resources. At some point they will collide (see #118) and you have no way of knowing that with this module as the resource will simply flap.

@DeviaVir
Copy link
Owner

I do think that should be the policy of this provider: whatever is in terraform is leading. In your plan you should be able to see the current user that you may be overwriting.

I don't entirely see how this would prevent #118 from happening either, a bad config (having the same primary_email twice and letting terraform flap between them) is not fixed by removing the import logic AFAICT.

@joshua-rutherford
Copy link
Contributor Author

joshua-rutherford commented Jan 13, 2020

I agree that if a person reviews the plan they will see there is something strange about to happen (i.e., I added a new user and it wants to change an existing user instead of creating a new one). However, that has two drawbacks in my mind:

  1. Requires human intervention and comprehension so hard to fully automate.
  2. Prone to human error should the human not pay close enough attention to the plan.

That aside, the fix to #118 is that new resources in my local state only ever call Insert which fails if the unique field exists and thus is easily detectable. Now it might be possible if someone runs terrafom import twice on the same GSuite user but that's a very explicit action and not one I can ever guard against. That is to say if you somehow get your state into a flapping situation this will not help you. This only helps prevent entering that state.

@DeviaVir
Copy link
Owner

I'm thinking that if you are running this in an automated way and you want it to error out, we add a field for specifically enabling that, e.g. overwrite_existing defaulted to true. Someone purely using a CI to manage users can set overwrite_existing to false so that terraform can error out for them whenever it would have overwritten an existing user. Does that take care of your usecase?

@joshua-rutherford
Copy link
Contributor Author

That would suit my needs fine. Can I make it global or do you want it per resource?

@DeviaVir
Copy link
Owner

@joshua-rutherford I suspect we should probably do both. We can set a default using a global parameter but override it per resource. Thoughts?

@DeviaVir
Copy link
Owner

Will cut a new release of the provider after this one is updated/merged.

@joshua-rutherford
Copy link
Contributor Author

Added a provider configuration and resource configuration for update_existing that defaults to true if not set. I only updated the gsuite_user resource though there are others this could be applied to. In some cases that's not straight forward as they are multi-level updates.

Copy link
Owner

@DeviaVir DeviaVir left a comment

Choose a reason for hiding this comment

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

👍 looks great, glad we found a solution that works for all use cases we could come up with!

@DeviaVir DeviaVir merged commit 8f1fa95 into DeviaVir:master Jan 17, 2020
@DeviaVir
Copy link
Owner

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants