-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
New resource: azurerm_user_assigned_identity
+ enabled UserAssigned identity for VM and VMSS
#1448
Conversation
There was a problem hiding this 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 |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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}" |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove this?
There was a problem hiding this comment.
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)), |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 | ||
} |
There was a problem hiding this comment.
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))
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(as above)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above reply..
@tombuildsstuff thank you for the review! |
There was a problem hiding this 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) |
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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, | ||
}, |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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)
User Assigned Identities tests pass:
|
@tombuildsstuff Your changes look good. |
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! |
Implementing feature mentioned in the feature request: #1377