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

New resource: azurerm_user_assigned_identity + enabled UserAssigned identity for VM and VMSS #1448

Merged
merged 16 commits into from
Jul 2, 2018

Conversation

logachev
Copy link
Contributor

Implementing feature mentioned in the feature request: #1377

@tombuildsstuff tombuildsstuff added enhancement service/vmss Virtual Machine Scale Sets labels Jun 27, 2018
Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

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

Hey @logachev

Thanks for this PR - apologies for the delayed review here!

I've taken a look through and left some comments inline, but this is off to a good start; if we can fix up the comments we should be able to run the tests and get this merged :)

Thanks!

User Assigned Identitites can be imported using the `resource id`, e.g.

```shell
terraform import azurerm_user_assigned_identity.testIdentity /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/acceptanceTestResourceGroup1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testIdentity
Copy link
Contributor

Choose a reason for hiding this comment

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

given this is a new Resource Provider, can we also ensure this is registered when the AzureRM Provider is initialized? This can be done by adding Microsoft.ManagedIdentity (which is case sensitive) to this list


* `resource_group_name` - The name of the resource group in which user assigned identity created.

* `location` - The location/region where the user assigned identity created.
Copy link
Contributor

Choose a reason for hiding this comment

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

can we remove name, resource_group_name and location here? these outputs can be implied as they're arguments

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed. Seems like there are two styles in .markdown files: some list arguments as attributes and some don't.

resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"

name = "${var.name}"
Copy link
Contributor

Choose a reason for hiding this comment

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

rather than using a variable, can we add an example name here? e.g. search-api

resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"

name = "test"
Copy link
Contributor

Choose a reason for hiding this comment

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

can we make this acctest%d rather than test - this'll help to prevent conflicts between acceptance test runs by appending the unique ID to the end

@@ -173,3 +220,203 @@ resource "azurerm_virtual_machine" "test" {
}
`, rInt, location, rInt, rInt, rInt, rInt, rInt)
}

func testAccAzureRMVirtualMachineSystemAssignedIdentityTemplate(rInt int, location string) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

minor we can remove the word Template from the end of this method name

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 removed it from new functions, but there are a lot of functions in this file following this pattern..


if resp.IdentityProperties == nil || resp.IdentityProperties.PrincipalID == nil {
return fmt.Errorf("Error PrincipalID can't be null for User Assigned Identity %q (Resource Group %q): %+v", resourceName, resGroup, err)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

can we remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(see above reply)

{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestMatchResourceAttr(resourceName, "id", regexp.MustCompile(resourceIdRegex)),
Copy link
Contributor

Choose a reason for hiding this comment

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

can we remove this check? if the ID doesn't match we'll get an error in the CRUD methods

for _, id := range *identity.IdentityIds {
identity_ids = append(identity_ids, id)
}
result["identity_ids"] = identity_ids
Copy link
Contributor

Choose a reason for hiding this comment

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

we need to ensure result["identity_ids"] is set all the time? this ensures we can still detect empty changes; the simplest way to do this is to make this:

identity_ids := make([]string, 0)
if identity.IdentityIds != nil {
  for _, id := range *identity.IdentityIds {
    identity_ids = append(identity_ids, id)
  }
}
result["identity_ids"] = identity_ids

identityType = compute.ResourceIdentityTypeUserAssigned
case strings.ToLower(string(compute.ResourceIdentityTypeSystemAssigned)):
identityType = compute.ResourceIdentityTypeSystemAssigned
}
Copy link
Contributor

Choose a reason for hiding this comment

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

we can make this:

identityType = compute.ResourceIdentityType(identity["type"].(string))

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 had what you advice in the first version. The problem with this was the fact that ResourceIdentityType is just a string. So, compute.ResourceIdentityType(identity["type"].(string) persists letters case.

As a result, identityType might be equal to userIdentity and it doesn't match compute.ResourceIdentityTypeUserAssigned string UserIdentity. So, you have to remember about this when you compare it later in code.

I think it's better to converge them during initialization, but I'd like to hear your recommendation.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's fine - in this case we can ensure the case matches the Constants/Enum's by updating the validation function / removing the Diff Suppress function, which will allow us to parse this directly:

ValidateFunc: validation.StringInSlice([]string{
 # ..
}, false)

identityType = compute.ResourceIdentityTypeUserAssigned
case strings.ToLower(string(compute.ResourceIdentityTypeSystemAssigned)):
identityType = compute.ResourceIdentityTypeSystemAssigned
}
Copy link
Contributor

Choose a reason for hiding this comment

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

(as above)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See above reply..

@tombuildsstuff tombuildsstuff added this to the Soon milestone Jun 29, 2018
@logachev
Copy link
Contributor Author

@tombuildsstuff thank you for the review!
I left a few replies to your comments to figure out the best way to address them and addressed remaining feedback.

@tombuildsstuff tombuildsstuff modified the milestones: Soon, 1.9.0 Jul 2, 2018
Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

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

hey @logachev

Thanks for pushing those changes - I've left a couple of comments (which I'm going to push a commit for, I hope you don't mind!) - but this otherwise LGTM 👍

Thanks!


log.Printf("[INFO] preparing arguments for Azure ARM user identity creation.")

resourceName := d.Get("name").(string)
Copy link
Contributor

Choose a reason for hiding this comment

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

🤦‍♂️ sorry I was thinking one thing and wrote another - can we name this variable name, to match the other resources? The name of the resource itself is fine :)

d.Set("resource_group_name", resGroup)
d.Set("location", resp.Location)
d.Set("name", resp.Name)
d.Set("principal_id", resp.IdentityProperties.PrincipalID.String())
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 sense in some scenarios, but would cause an error when running terraform plan (when this is outside of the users control, for instance if Azure returns a different schema than is defined, it shouldn't break Terraform) - as such we need to not return an error here, can update this using the code sample you posted?

Delete: resourceArmUserAssignedIdentityDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd missed there wasn't an Import test for this (these are tracked in a separate file) - I've included this in the commit (but here's an example); these verify the state set via d.Set matches the configuration used to create it (by creating the resource, then removing it from the state, then running terraform import and ensuring the config matches the state)

```
acctests azurerm TestAccAzureRMUserAssignedIdentity_
=== RUN   TestAccAzureRMUserAssignedIdentity_importBasic
--- PASS: TestAccAzureRMUserAssignedIdentity_importBasic (80.67s)
=== RUN   TestAccAzureRMUserAssignedIdentity_basic
--- PASS: TestAccAzureRMUserAssignedIdentity_basic (78.45s)
PASS
ok  	github.com/terraform-providers/terraform-provider-azurerm/azurerm	159.156s
```
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMVirtualMachineScaleSetDestroy,
Copy link
Contributor

Choose a reason for hiding this comment

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

rather than using the VMSS CheckDestroy function - I'm going to push a commit to use one specific for User Assigned Identities (this ensures that when the resource is destroyed by Terraform, it's not lingering around)

@tombuildsstuff
Copy link
Contributor

User Assigned Identities tests pass:

acctests azurerm TestAccAzureRMUserAssignedIdentity_
=== RUN   TestAccAzureRMUserAssignedIdentity_importBasic
--- PASS: TestAccAzureRMUserAssignedIdentity_importBasic (80.67s)
=== RUN   TestAccAzureRMUserAssignedIdentity_basic
--- PASS: TestAccAzureRMUserAssignedIdentity_basic (78.45s)
PASS
ok  	github.com/terraform-providers/terraform-provider-azurerm/azurerm	159.156s

@tombuildsstuff
Copy link
Contributor

VM tests pass:

screenshot 2018-07-02 at 14 21 38

VM Scale Set tests pass:

screenshot 2018-07-02 at 14 21 41

@tombuildsstuff tombuildsstuff merged commit 241525e into hashicorp:master Jul 2, 2018
tombuildsstuff added a commit that referenced this pull request Jul 2, 2018
@logachev
Copy link
Contributor Author

logachev commented Jul 2, 2018

@tombuildsstuff Your changes look good.
Sorry, I missed import tests and didn't notice destroy function is not some generic function.
Thank you for your assistance!

@ghost
Copy link

ghost commented Mar 30, 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 feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks!

@ghost ghost locked and limited conversation to collaborators Mar 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement service/vmss Virtual Machine Scale Sets
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants