atlassian / terraform-provider-artifactory

Terraform provider to manage Artifactory
Apache License 2.0
89 stars 42 forks source link

Support reading existing objects that are not managed by tf #68

Open Taoquitok opened 4 years ago

Taoquitok commented 4 years ago

Community Note

Description

I'm currently managing an artifactory instance were some users are managed by TF, and some are not (I know... don't ask...).
Blindly adding users to TF causes their passwords to be reset as TF plan reports it will "add" (create) the users rather than modify, and TF apply just reports they've been created, presumably as it's not aware that it's inadvertently overwriting... which for a bulk import of all users to bring them into state would be very disruptive.

I've experimented with using terraform Import, but it's cumbersome and requires an external loop over all named resources as it doesn't seem to accommodate for importing the whole run.
As a good work around, and useful extension to this provider, It would be useful if either the existing artifactory_user resource did some validation checks against artifactory (or had a flag to allow for this).
Alternatively if there was a data source for each available resource (or at least artifactory_user) to allow for gathering of unmanaged state then that could be used as a base for migrating un-managed to a managed state.

New or Affected Resource(s)

artifactoryuser data artifactory*

Potential Terraform Configuration

variable "users_group_map" {
  type = list(object({ name = string, email = string, groups = list(string) }))

  default = [
    {
      name   = "managed_user"
      email  = "managed_user@domain.com"
      groups = ["group1"]
    },
    {
      name   = "unmanaged_user1"
      email  = "unmanaged_user1@domain.com"
      groups = ["group1"]
    },
    {
      name   = "unmanaged_user2"
      email  = "unmanaged_user2@domain.com"
      groups = ["group1"]
    }
  ]
}

resource "artifactory_user" "user" {
  count  = length(var.users_group_map)
  name   = var.users_group_map[count.index]["name"]
  email  = var.users_group_map[count.index]["email"]
  groups = var.users_group_map[count.index]["groups"]
}
# example of using terraform import, looping over all users is plausible, but clunky
terraform init
terraform import artifactory_user.user[0] unmanaged_user1
terraform import artifactory_user.user[1] unmanaged_user2
...
terraform import artifactory_user.user[999] unmanaged_user999
# etc
jamestoyer commented 4 years ago

Which version of the provider are you using? By default in v2.0.0-alpha1 if you do not set a password on a user it will not manage the password or change it. I can confirm this is the behaviour as we have imported many users using this method. The docs I have written around this should also confirm this behaviour, although I'm happy to update if incorrect:

Note: User passwords are never returned through the API. Since they are never returned they cannot be managed by directly through Terraform. However, it is possible to store a "known" state for the password and make changes if it's updated in Terraform. If no password is given a random one is created otherwise that value is used. It's also worth noting "removing" the password argument does not reset the password; it just removes Terraform from storing the "known" state.

I also believe your import commands are incorrect for the example you listed. The correct syntax is:

terraform import "artifactory_user.user[1]" unmanaged_user1
terraform import "artifactory_user.user[2]" unmanaged_user2
Taoquitok commented 4 years ago

Which version of the provider are you using?

We're building the provider off master. A quick comparison to v2.0.0-alpha1 doesn't show any obvious user affecting differences that could explain why passwords are being reset.
For sanity I've just tested with a brand new user, created them manually, confirmed can log in, and then ran terraform. Plan and apply both reported a creation artifactory_user.user[0]: Creation complete after 1s [id=testuser], and relogging with that user confirmed that their password has now been reset, so in the case of attempting to manage an existing object, if it's not already in terraform it will get overridden.

I also believe your import commands are incorrect for the example you listed. The correct syntax is:

Thanks for the correction, I've tested your suggestion and corrected my issue to reflect that it does work as expected to import, though would still be clunky to complete / repeat on a regular basis to resolve any manual creations.