Public/Invoke-MgkTenantSweep.ps1
|
function Invoke-MgkTenantSweep { <# .SYNOPSIS Runs a scriptblock against every tenant in a fleet, fault-isolated. .DESCRIPTION For each tenant: connect to Graph (certificate app-only), invoke the scriptblock (which receives the tenant config object), disconnect. Guarantees: - one tenant's failure never stops the sweep (it becomes a result row with Success=$false and the error message) - throttling (429) and transient 5xx are retried with backoff - Disconnect-MgGraph always runs, even on failure .PARAMETER Tenant Tenant config objects (from Get-MgkTenantConfig), by pipeline or parameter. .PARAMETER ScriptBlock Work to run per tenant. Receives the tenant object as its argument. Whatever it returns lands in the result's Data property. .OUTPUTS One MspGraphKit.SweepResult per tenant: TenantName, Success, Data, Error, DurationMs. .EXAMPLE $r = Get-MgkTenantConfig -Path tenants.json | Invoke-MgkTenantSweep -ScriptBlock { param($t) (Invoke-MgGraphRequest -Uri 'https://graph.microsoft.com/v1.0/organization').value.displayName } .EXAMPLE Invoke-MgkTenantSweep -Tenant $tenants -ScriptBlock $work -Verbose #> [CmdletBinding()] [OutputType('MspGraphKit.SweepResult')] param( [Parameter(Mandatory, ValueFromPipeline)] [PSTypeName('MspGraphKit.TenantConfig')] [object[]]$Tenant, [Parameter(Mandatory)] [scriptblock]$ScriptBlock ) process { foreach ($t in $Tenant) { Write-Verbose "Sweeping $($t.TenantName)" $sw = [System.Diagnostics.Stopwatch]::StartNew() $result = [ordered]@{ PSTypeName = 'MspGraphKit.SweepResult' TenantName = $t.TenantName Success = $false Data = $null Error = $null DurationMs = 0 } try { Connect-MgGraph -TenantId $t.TenantId -ClientId $t.ClientId ` -CertificateThumbprint $t.CertificateThumbprint -NoWelcome -ErrorAction Stop $result.Data = Invoke-MgkWithRetry -ScriptBlock $ScriptBlock -ArgumentList @($t) $result.Success = $true } catch { $result.Error = "$_" Write-Warning "$($t.TenantName): $_" } finally { $result.DurationMs = $sw.ElapsedMilliseconds Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null } [pscustomobject]$result } } } |