tools/AduCmdlets/AduRestApi.psm1 (192 lines of code) (raw):

# # Device Update for IoT Hub # PowerShell module for calling Device Update for IoT Hub REST API (ADU). # Copyright (c) Microsoft Corporation. # #Requires -Version 5.0 $API_VERSION = "api-version=2021-06-01-preview" # -------------------------------------------------------------------------------------------------------------------------------- # INTERNAL METHODS # -------------------------------------------------------------------------------------------------------------------------------- function Get-AuthorizationHeaders { Param( [ValidateNotNullOrEmpty()] $AccessToken = $(throw "'AccessToken' parameter is required.") ) return @{ 'Authorization' = "Bearer $AccessToken" } } # -------------------------------------------------------------------------------------------------------------------------------- # EXPORTED METHODS # -------------------------------------------------------------------------------------------------------------------------------- function Start-AduImportUpdate { <# .SYNOPSIS Start importing an update to Device Update for IoT Hub. Method returns an operationId to be used for polling the operation status. .EXAMPLE PS > $updateId = New-AduUpdateId -Provider Fabrikam -Name Toaster -Version 2.0 PS > $compatInfo = New-AduUpdateCompatibility -Manufacturer Fabrikam -Model Toaster PS > PS > $input = New-AduImportUpdateInput -UpdateId $updateId ` -UpdateType microsoft/swupdate:1 -InstalledCriteria 5 ` -Compatibility $compatInfo` -Files '.\file1.json', '.\file2.zip' PS > PS > Start-AduImportUpdate -AccountEndpoint sampleaccount.api.adu.microsoft.com -InstanceId sampleinstance ` -AuthorizationToken 'sample token' ` -ImportUpdateInput $input #> [CmdletBinding()] Param( # ADU account endpoint, e.g. sampleaccount.api.adu.microsoft.com [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $AccountEndpoint, # ADU Instance Id. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $InstanceId, # Azure Active Directory OAuth Authorization Token. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $AuthorizationToken, # ADU Import Update API input(s). [Parameter(ParameterSetName="Default", Mandatory=$true)] [ValidateCount(1, 11)] [psobject[]] $ImportUpdateInput, # Raw API request body in JSON string format. [Parameter(ParameterSetName="Advanced", Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $RequestBody ) $url = "https://$AccountEndpoint/deviceupdate/$InstanceId/updates?$API_VERSION&action=import" $headers = Get-AuthorizationHeaders -AccessToken $AuthorizationToken $headers.Add('Content-Type', 'application/json') if ($ImportUpdateInput) { $RequestBody = ConvertTo-Json -InputObject $ImportUpdateInput -Depth 50 } Write-Verbose $RequestBody $response = Invoke-WebRequest -Uri $url -Method POST -Headers $headers -Body $RequestBody -UseBasicParsing -Verbose:$VerbosePreference if ($response.StatusCode -ne 202) { Write-Error $response } # .../updates/operations/86b1c73c-e041-4eea-bc7b-918248ae66da?api-version=2021-06-01-draft $operationId = $response.Headers["Operation-Location"].Split('/')[-1].Split('?')[0] return $operationId } function Get-AduUpdateOperation { <# .SYNOPSIS Get Update Operation entity. .EXAMPLE PS > Get-AduUpdateOperation -AccountEndpoint sampleaccount.api.adu.microsoft.com -InstanceId sampleinstance ` -AuthorizationToken 'sample token' ` -OperationId ceed45ee-3461-4ee3-b321-d3e36b6eacc7 #> [CmdletBinding()] Param( # ADU account endpoint, e.g. sampleaccount.api.adu.microsoft.com [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $AccountEndpoint, # ADU Instance Id. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $InstanceId, # Azure Active Directory OAuth authorization token. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $AuthorizationToken, # Operation identifier returned by Import/Delete Update API. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $OperationId, # If specified, will be populated with API response headers. [hashtable] $ResponseHeaders = $null ) $url = "https://$AccountEndpoint/deviceupdate/$InstanceId/updates/operations/$($operationId)?$API_VERSION" $headers = Get-AuthorizationHeaders -AccessToken $AuthorizationToken $response = Invoke-WebRequest -Uri $url -Method GET -Headers $headers -UseBasicParsing -Verbose:$VerbosePreference $operation = $response.Content | ConvertFrom-Json if ($ResponseHeaders -ne $null) { $response.Headers.GetEnumerator() | ForEach-Object { $ResponseHeaders.Add($_.Key, $_.Value[0]) } } return $operation } function Wait-AduUpdateOperation { <# .SYNOPSIS Poll update operation until completion. .EXAMPLE PS > Wait-AduUpdateOperation -AccountEndpoint sampleaccount.api.adu.microsoft.com -InstanceId sampleinstance ` -AuthorizationToken 'sample token' ` -OperationId ceed45ee-3461-4ee3-b321-d3e36b6eacc7 #> [CmdletBinding()] Param( # ADU account endpoint, e.g. sampleaccount.api.adu.microsoft.com [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $AccountEndpoint, # ADU Instance Id. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $InstanceId, # Azure Active Directory OAuth authorization token. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $AuthorizationToken, # Operation identifier returned by Import/Delete Update API. [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $OperationId, # How long to wait before timing out. [timespan] $Timeout = (New-TimeSpan -Minutes 30) ) Write-Host "Waiting for operation $operationId to complete " -NoNewline if ($VerbosePreference) { Write-Host '...' } $endTime = (Get-Date).Add($Timeout) do { $responseHeaders = @{} $operation = Get-AduUpdateOperation -AccountEndpoint $AccountEndpoint -InstanceId $InstanceId -AuthorizationToken $AuthorizationToken ` -OperationId $operationId -ResponseHeaders $responseHeaders -ErrorAction Stop [int] $retryAfterInSecs = $responseHeaders["Retry-After"] if ($VerbosePreference) { Write-Verbose "Operation status: $($operation.Status), TraceId: $($operation.TraceId)" } else { Write-Host '.' -NoNewline } if ($operation.Status -eq 'Failed' -or $operation.Status -eq 'Succeeded') { break; } Start-Sleep -Seconds $retryAfterInSecs } while ((Get-Date) -lt $endTime) Write-Host '' $operation | ConvertTo-Json -Depth 20 | Out-Host if ($operation.Status -ne 'Succeeded') { Write-Error "Operation $Operationid had failed." } else { Write-Host "Operation $OperationId had completed successfully." -ForegroundColor Green } } Export-ModuleMember -Function Start-AduImportUpdate, Get-AduUpdateOperation, Wait-AduUpdateOperation