Closed MattKotsenas closed 2 years ago
Current Azure Cmdlets have thread conflicts especially around context. Did you mean you hope to use different subscriptions/contexts in current process?
Another question, subscription id can be parameter of Set-AzContext. Is it helpful?
Current Azure Cmdlets have thread conflicts especially around context. Did you mean you hope to use different subscriptions/contexts in current process?
Yes. For instance, imagine a main script that calls into multiple scripts, each of which calls Azure PowerShell commands for a separate subscription. Ideally those scripts could be run in parallel, but because the are all running in the same process, if any one calls Set-AzContext
, it affects the others.
Another question, subscription id can be parameter of Set-AzContext. Is it helpful?
Not in this case. The problem is that Set-AzContext
has side-effects.
The problem / goal is to get a context for any subscription without needing to first call Set-AzContext
.
There are two issues at work here:
Set-AzContext -Subscription <sub>
changes the subscription property of the default context (potentially overwriting a different subscription)
While
Set-AzContext -Name <name> -Subscription <sub-d>
Will create a new Context if 'Name' is unique. Conversely, Get-AzContext -Name <name>
will get the named context regardless of which context is selected.
The advice for multithreaded access is:
Use the output of Connect-AzAccount as the context Container you pass into cmdlets. You can use the 'SubscriptionId' parameter of the cmdlet to have a particular context selected in the output context container. You can use connect-AzAccount multiple times ina script, the token cache should allow tokens to be resused on subsequent logins
You may also use Set-AzContext -Name
, providing a unque name to each context (you could for example, name the contexts by subscription Id, if that works in your scenario). Get-AzContext -Name would always return the expected context in each scenario. For example, here is a script that renames all your context to use just the subscription id:
Get-AzContext -ListAvailable | %{Rename-AzContext -TargetName $_.Subscription.Id -InputObject $_}
And then you could simply use the result of Select-AzContext -Name <sub-id>
to always return the expected context, even in multi-threaded scenarios.
As a long term matter, since Azure is moving toward many more multi-subscription operations, I think the best solution would be to separate the selected subscription from the credentials - if you could pass a subscription to each cmdlet without needing to pass the context, it would make these scenarios much easier to figure out without documentation or expert help.
Do you have an update regarding the more than 25 subscriptions issue? I don't have the issue on my local computer but when I'm using Get-AzContext (same Az PowerShell version: Az.Accounts v2.7.2) on Azure on my Durable Function with System Managed Identity to all my subscriptions with Reader permission, I can only retrieve 25 AzContext within my 32 Azure subscriptions.
As mentioned by @MattKotsenas , Set-AzContext has a side effect, it's really long to set an AzContext
I need all my AzContext from my Azure subscriptions for using this function: Get-AzConsumptionUsageDetail (= so no i cann pass the subscription for that function, I can only give an AzContext) I use Start-ThreadJob, so I can retrieve my consumption usage detail from all my subscriptions in a faster way But since I can only got 25 AzContext, my total consumption usage (based on my Azure Tag), I incorrect when i run my Durable Function on my Azure Function App.. I don't have any issue to get my 25 AzContext on my local machine with the Azure Function Core Tools. I made a ticket to MS Support, they are investigating but wondering if the issue could come from Azure Powershell itself even though it works locally...
@MattKotsenas I figured out the issue that you mentioned, hope it will help in your case:
# Note that there's no way to convert this object to
# Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer
# without calling Set-AzContext
$azSubscriptionContext = Get-AzContext -Name $subscriptionContextName
$converter = New-Object -TypeName Microsoft.Azure.Commands.Profile.Models.AzureContextConverter
$azSubscriptionContext = $converter.ConvertFrom($azSubscriptionContext, [Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer], $null, $true)
then you can use the -AzContext parameter with $azSubscriptionContext
-MaxContextPopulation
of Connect-AzAccount
determines the total number of context populated. Default value is 25. Please try it.
Thanks a lot @dingmeng-xue You make my day. I can finally collect my Azure Consumption Usage from all my subscriptions via an Azure Durable Function using Start-ThreadJob. It took 15min instead of 40 to 60min to collect all the data.
It will be great if Microsoft can add a note link in Get-AzContext doc page about this option in Connect-AzAccount
One note for anyone else who runs into this issue -- if you are already authenticated in a PowerShell session, running Connect-AzAccount again will not take on the new context population value, because these context objects are cached in a singleton object under the surface. You first have to Disconnect-AzAccount
to clear that cache, then you can run your connect command with the number of contexts you would like.
Reference: https://github.com/Azure/azure-powershell/issues/14482
Description
Az cmdlets all take a
-DefaultProfile
or-AzContext
parameter to allow operating against a specific subscription. These parameters take an IAzureContextContainter, which can be retrieved fromGet-AzContext
.Using either of these parameters allows a user to avoid changing the default context (i.e. without calling
Set-AzContext
). However, there are two scenarios for us that both cause subscriptions to be missing from the list of contexts:-SkipContextPopulation
switchIn either of these cases it is impossible to create an
IAzureContextContainer
without changing the default context, which is a process-wide or user-wide setting, and so changing it can break multi-threaded scenarios.Steps to reproduce
Environment data
Module versions