numerous-engineer-99269
04/29/2024, 4:41 PMInputList<string>
of Azure role ids I'm accessing in a custom component. Essentially I'm trying to loop over the roles and create a new AzureNative.Authorization.RoleAssignment
for each ID. Initially I was successful, until I changed a name (trigger a teardown of the old resources). The error looks like so:
Type Name Status Info
pulumi:pulumi:Stack api-infra-data-dev **failed** 1 error
+ └─ custom-component:authorization:RoleAssignment mi-storage-account-api-roles created
+ ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0002 created (0.15s)
+ ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0001 created (0.31s)
+ ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0003 created (0.45s)
+ ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0004 created (0.61s)
+ ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0002 **creating failed** 1 error
+ ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0001 **creating failed** 1 error
+ ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0003 **creating failed** 1 error
+ └─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0004 **creating failed** 1 error
More details:
azure-native:authorization:RoleAssignment (dev-mi-storage-account-api-roles-role-assignment-eus2-0002):
error: autorest/azure: Service returned an error. Status=<nil> Code="RoleAssignmentExists" Message="The role assignment already exists."
Based on the output of the command line it appears it did not attempt to remove the old resources first. I'm guessing the issue is because of using a foreach in an apply function. This is how it's written using Apply
args.RoleDefinitionId.Apply(roles =>
{
var instance = args.Instance;
foreach (var roleId in roles)
{
AssignSingleRole(name, roleId, args, instance);
instance++;
}
return "";
});
Reading through issues/posts I've learned it's not the right practice.
But I'm failing to understand what is the right practice for looping over InputList<T>
. I'm running into a wall. Does anyone have an example or direction for how to properly loop over InputList? Thank you.modern-boots-64313
04/29/2024, 5:17 PMAssignSingleRole(name ...)
, what's the name
parameter used for ? I don't really work on Azure but i suppose the RoleAssignment resource name shouldn't be duplicatednumerous-engineer-99269
04/29/2024, 5:21 PMpublic RoleAssignment(string name, RoleAssignmentArgs args, ComponentResourceOptions? options = null)
: base($"custom-component:authorization:{nameof(RoleAssignment)}", name, options)
In AssignSingleRole(name ...)
the name is extending upon for a Random UUID, and Role Assignment. That said, the name shouldn't be duplicated, and from what I can tell it isn't.numerous-engineer-99269
04/29/2024, 5:25 PMmi-storage-account-api-roles
And the component resource names look like this:
dev-mi-storage-account-api-roles-role-assignment-id-eus2-0001
dev-mi-storage-account-api-roles-role-assignment-eus2-0001
modern-boots-64313
04/29/2024, 5:37 PMnumerous-engineer-99269
04/29/2024, 5:42 PM+ ├─ custom-component:authorization:RoleAssignment mi-storage-account-api-rolesz create
+ │ ├─ random:index:RandomUuid dev-mi-storage-account-api-rolesz-role-assignment-id-eus2-0002 create
+ │ ├─ random:index:RandomUuid dev-mi-storage-account-api-rolesz-role-assignment-id-eus2-0001 create
+ │ ├─ random:index:RandomUuid dev-mi-storage-account-api-rolesz-role-assignment-id-eus2-0003 create
+ │ ├─ random:index:RandomUuid dev-mi-storage-account-api-rolesz-role-assignment-id-eus2-0004 create
+ │ ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-rolesz-role-assignment-eus2-0001 create
+ │ ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-rolesz-role-assignment-eus2-0002 create
+ │ ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-rolesz-role-assignment-eus2-0004 create
+ │ └─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-rolesz-role-assignment-eus2-0003 create
- └─ custom-component:authorization:RoleAssignment mi-storage-account-api-roles delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0001 delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0004 delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0003 delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0002 delete
- ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0002 delete
- ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0003 delete
- ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0001 delete
- └─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0004 delete
Resources:
+ 9 to create
- 9 to delete
18 changes. 2 unchanged
The change is from mi-storage-account-api-roles
to mi-storage-account-api-rolesz
-- as seen in the output, all the resources that have the substring ``mi-storage-account-api-roles` are marked for deletion.modern-boots-64313
04/29/2024, 5:46 PMpulumi up
numerous-engineer-99269
04/29/2024, 5:46 PMpublic class RoleAssignment : ComponentResource
{
public RoleAssignment(string name, RoleAssignmentArgs args, ComponentResourceOptions? options = null)
: base($"custom-component:authorization:{nameof(RoleAssignment)}", name, options)
{
// Issues looping over InputList -- disabled until feedback is provided.
// args.RoleDefinitionId.Apply(roles =>
// {
// var instance = args.Instance;
// foreach (var roleId in roles)
// {
// AssignSingleRole(name, roleId, args, instance);
// instance++;
// }
//
// return "";
// });
var instance = args.Instance;
foreach (var roleId in args.RoleDefinitionId)
{
AssignSingleRole(name, roleId, args, instance);
instance++;
}
// var roleId = args.RoleDefinitionId.Apply(x => x.Single());
// AssignSingleRole(name, roleId, args);
}
private void AssignSingleRole(string name, Input<string> id, RoleAssignmentArgs args, int instance)
{
var roleDefinition = GetRoleDefinition.Invoke(new ()
{
RoleDefinitionId = id,
Scope = $"/subscriptions/{args.SubscriptionId}"
});
var newRoleId = new Random.RandomUuid(
args.NameBuilder.GenerateNameWithLocation($"{name}-role-assignment-id", "", instance),
Random.RandomUuidArgs.Empty,
new CustomResourceOptions
{
Parent = this,
DeleteBeforeReplace = true,
});
var roleAssignment = new AzureNative.Authorization.RoleAssignment(
args.NameBuilder.GenerateNameWithLocation($"{name}-role-assignment", "", instance),
new ()
{
Scope = args.Scope,
RoleDefinitionId = roleDefinition.Apply(x => x.Id),
PrincipalId = args.PrincipalId,
PrincipalType = args.PrincipalType,
RoleAssignmentName = newRoleId.Id
},
new CustomResourceOptions
{
Parent = this,
DependsOn = { newRoleId },
DeleteBeforeReplace = true,
});
}
}
public class RoleAssignmentArgs
{
public int Instance { get; set; }
public ResourceNameBuilder NameBuilder { get; set; } = null!;
public string SubscriptionId { get; set; } = null!;
public Input<string> Scope { get; set; } = null!;
public List<string> RoleDefinitionId { get; set; } = null!;
public Input<string> PrincipalId { get; set; } = null!;
public PrincipalType PrincipalType { get; set; }
}
And here's how to use it.
var roleAssignmentsApiStorageAccount = new CustomAuthorization.RoleAssignment(
"mi-storage-account-api-roles",
new RoleAssignmentArgs
{
Instance = 1,
NameBuilder = context.NameBuilder,
SubscriptionId = context.SubscriptionId,
Scope = storageAccountApi.Apply(x => x.Id),
RoleDefinitionId = [
AzureBuiltInRoleDefinitions.StorageAccountContributor,
AzureBuiltInRoleDefinitions.StorageBlobDataContributor,
AzureBuiltInRoleDefinitions.StorageQueueDataContributor,
AzureBuiltInRoleDefinitions.StorageTableDataContributor,
],
PrincipalId = context.ManagedIdentity.Apply(x => x.PrincipalId),
PrincipalType = AzureNative.Authorization.PrincipalType.ServicePrincipal,
});
numerous-engineer-99269
04/29/2024, 5:47 PMpublic List<string> RoleDefinitionId
to a regular list to troubleshoot.numerous-engineer-99269
04/29/2024, 5:50 PMpulumi up
output given match.numerous-engineer-99269
04/29/2024, 5:59 PMerror: autorest/azure: Service returned an error. Status=<nil> Code="RoleAssignmentExists" Message="The role assignment already exists."
I've run pulumi up
multiple times and it fails to remove the previous role assignment. Here's what the preview output looks like:
Type Name Plan
pulumi:pulumi:Stack api-infra-data-dev
├─ custom-component:authorization:RoleAssignment testing-name-collision
+ │ ├─ azure-native:authorization:RoleAssignment dev-testing-name-collision-role-assignment-eus2-0001 create
+ │ ├─ azure-native:authorization:RoleAssignment dev-testing-name-collision-role-assignment-eus2-0003 create
+ │ ├─ azure-native:authorization:RoleAssignment dev-testing-name-collision-role-assignment-eus2-0002 create
+ │ └─ azure-native:authorization:RoleAssignment dev-testing-name-collision-role-assignment-eus2-0004 create
- └─ custom-component:authorization:RoleAssignment mi-storage-account-api-roles delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0003 delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0004 delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0002 delete
- ├─ azure-native:authorization:RoleAssignment dev-mi-storage-account-api-roles-role-assignment-eus2-0001 delete
- ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0002 delete
- ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0001 delete
- ├─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0004 delete
- └─ random:index:RandomUuid dev-mi-storage-account-api-roles-role-assignment-id-eus2-0003 delete
Resources:
+ 4 to create
- 9 to delete
numerous-engineer-99269
04/29/2024, 6:00 PMCustomResourceOptions.DeleteBeforeReplace
handle removing the resource before attempting to re-create?modern-boots-64313
04/29/2024, 6:04 PMnumerous-engineer-99269
04/29/2024, 6:19 PMInputList<string>
issue after all. Based on this code used for iterating over an input list, does this seem correct to you?
args.RoleDefinitionId.Apply(roles =>
{
var instance = args.Instance;
foreach (var roleId in roles)
{
AssignSingleRole(name, roleId, args, instance);
instance++;
}
return "";
});
I've read it's not the best way... But I cannot find an alternative. So just want to make sure.
Also, thanks for the help @modern-boots-64313modern-boots-64313
04/29/2024, 6:38 PMnumerous-engineer-99269
04/30/2024, 11:36 AM