Powershell Foreach-Object parallel with az cli profile isolation

832 views Asked by At

I have a script that need to call child scripts in parallel. Child scripts using az cli and create/modify Azure PaaS objects in different Azure subscriptions.
The problem is that as different scripts are using az account set --subscription <subscription-for-script>, they overlap and something that need to be created in subscription A by script A, created in subscription B cause a moment before script B set subscription to subscription B. As az cli stores context in AzureProfile.json, I tried to create new folder per script and via $Env:AZURE_CONFIG_DIR specify different values per script. But I cannot find a way to isolate environment variables in child scripts, or specify AzureProfile context without using environment variables. In parent script:

$listOfScripts | Foreach-Object -Parallel {
  <block to run script with arguments>
} -AsJob -ThrottleLimit 50

and in each child script:

$Env:AZURE_CONFIG_DIR = "$RootPath\..\AzureProfiles\folderForScript"
az login --service-principal -u ${env:ARM_CLIENT_ID} -p ${env:ARM_CLIENT_SECRET} --tenant ${env:ARM_TENANT_ID}
az account set --subscription $subscription_id

Would be appreciate for advice how could be achieved running parallel independent scripts that uses different subscriptions to modify Azure PaaS objects

Update: Only solution that found - not to use az login and az account set inside scripts that run in parallel. Just connect via SPN in parent script and use parameter --subscription in each az command.

1

There are 1 answers

0
Delliganesh Sevanesan On

Run script block in parallel

Script blocks run in a runspace context in a PowerShell. It contains all the defined variables, functions & loaded modules. Initializing a runspace for script to run in takes time and resources. It must be run within their own runspace when scripts are running in parallel. Each runspace must load whatever module is needed and have any variable be explicitly passed in from the calling script.

The only variable that automatically appears in the parallel script block is the piped in object. Other variables are passed in using the $using: keyword.

Example

$computers =  'computerA','computerB','computerC','computerD' 
$logsToGet =  'LogA','LogB','LogC'  
# Read specified logs on each machine, using custom module 
$logs = $computers |  ForEach-Object  -ThrottleLimit  10  -Parallel  {  
Import-Module  MyLogsModule  
Get-Logs  -ComputerName $_ -LogName $using:logsToGet 
}

References