Public/Update-UnifiedContacts.ps1
function Update-UnifiedContacts { [CmdletBinding()] Param( [Parameter (Mandatory = $true, HelpMessage = "The Url you can copy from your browser when you open the App Service. Format: https://portal.azure.com/#<domain>/resource/subscriptions/<subscriptionId>/resourceGroups/<ressourceGroupName>/providers/Microsoft.Web/sites/<appServiceName>/appServices")][string]$AppServiceAzureUrl, [Parameter (Mandatory = $false, HelpMessage = "Choose your release channel.")][string]$ReleaseChannel = $null ) $ErrorActionPreference = "Stop" #$Script:AppServiceAzureUrl = $AppServiceAzureUrl; $ResourceGroup = (($AppServiceAzureUrl -Split "resourceGroups/")[1] -Split "/")[0] $SubscriptionId = (($AppServiceAzureUrl -Split "subscriptions/")[1] -Split "/")[0] $AppServiceName = (($AppServiceAzureUrl -Split "sites/")[1] -Split "/")[0] Write-Host "ResourceGroup: $ResourceGroup`nSubscriptionId: $SubscriptionId`nAppServiceName: $AppServiceName" Import-Module Az.Resources try { Get-LatestModuleVersion try { $context = Get-AzContext } catch { #fall through } if ($null -eq $context) { [void] (Connect-AzAccount -Subscription $SubscriptionId) } elseif ($context.Subscription.Id -ne $SubscriptionId) { [void] (Set-AzContext -Subscription $SubscriptionId) } $response = Invoke-WebRequest -Uri $Script:versionManifesUri -UseBasicParsing if ($response.StatusCode -lt 200 -or $response.StatusCode -ge 300) { throw "Could not accquire versionManifest" } Write-Progress -Activity "Update Unified Contacts" -Status "Get Web App Information" -PercentComplete 5 $versionManifest = $response.Content | ConvertFrom-Json $appService = Get-AzWebApp -ResourceGroupName $ResourceGroup -Name $AppServiceName if ($null -eq ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq $Script:AppServiceAzureUrlPropertyName })) { $settings = @{} foreach ($appsetting in $appService.SiteConfig.AppSettings) { $settings.add($appsetting.Name, $appsetting.Value) } $settings.add($Script:appServiceAzureUrlPropertyName, $AppServiceAzureUrl) Set-AzWebApp -ResourceGroupName $ResourceGroup -Name $AppServiceName -AppSettings $settings } $storageAccountName = ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq $Script:storageAccountPropertyName }).value $destContext = New-AzStorageContext -StorageAccountName $storageAccountName $me = Get-AzADUser -UserPrincipalName (az account show --query user.name --output tsv) Write-Progress -Activity "Update Unified Contacts" -Status "Check necessary permissions" -PercentComplete 15 $role = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor" if ($null -eq $role) { New-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor" | Out-Null $roleReady = $null while ($null -eq $roleReady) { Start-Sleep -Seconds 10 $roleReady = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor" } } Write-Progress -Activity "Update Unified Contacts" -Status "Get selected release channel" -PercentComplete 25 $selectedChannel = $versionManifest.channels | Where-Object { $_.name -eq $releaseChannel } if ($null -eq $releaseChannel -or $null -eq $selectedChannel ) { $title = "From which release channel do you want to update?" $prompt = "Enter your choice" $default = 0 $choicesRaw = @("&Stable", "&Preview", "&Nightly") $releaseChannelName = @() $choices = [System.Management.Automation.Host.ChoiceDescription[]] @() $choicesRaw | ForEach-Object { $choices += [System.Management.Automation.Host.ChoiceDescription]$_ $releaseChannelName += $_.TrimStart("&").ToLower() } $releaseChannel = $host.UI.PromptForChoice($title, $prompt, $choices, $default) $selectedChannel = $versionManifest.channels | Where-Object { $_.name -eq $releaseChannelName[$releaseChannel] } } Write-Progress -Activity "Update Unified Contacts" -Status "Copy Binaries" -PercentComplete 50 Start-AzStorageBlobCopy -AbsoluteUri $selectedChannel.latestVersionRef -DestContainer "unified-contacts" -DestBlob "binaries.zip" -DestContext $destContext -Force | Out-Null $role = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Table Data Contributor" if ($null -eq $role) { New-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Table Data Contributor" | Out-Null $roleReady = $null while ($null -eq $roleReady) { Start-Sleep -Seconds 10 #wait for roleassignment to be present in Entra Id $roleReady = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Table Data Contributor" } } Update-Infrastructure -ResourceGroupName $ResourceGroup -SubscriptionId $SubscriptionId -destContext $destContext Write-Progress -Activity "Update Unified Contacts" -Status "Restart Web App" -PercentComplete 75 Restart-AzWebApp -ResourceGroupName $ResourceGroup -Name $AppServiceName | Out-Null Start-Sleep -Seconds 20 $timeout = (Get-Date).AddMinutes(5) $responseReady = $null $headers = @{ "Content-Type" = "application/json" } $checkApiEndpoint = "https://$($appService.hostnames[0])/v1.3.0/api/general/version" $timeout = (Get-Date).AddMinutes(10) $restartedWebApp = $false while ((Get-Date) -lt $timeout) { Start-Sleep -Seconds 5 if ((Get-AzWebApp -Name $AppServiceName -ResourceGroupName $ResourceGroup).State -eq "Running") { # AppService has successfully restarted if we get a 2XX returned with the current version $responseReady = $null try { $responseReady = Invoke-WebRequest -Uri $checkApiEndpoint -Method Get -Headers $headers -ErrorAction 'SilentlyContinue' } catch [Microsoft.PowerShell.Commands.HttpResponseException] { $responseReady = $_.Exception.Response } catch { Write-Warning "No Http-Error was thrown: $_" } if ($null -ne $responseReady -and $responseReady.StatusCode -ge 200 -and $responseReady.StatusCode -le 299 -and $null -ne $responseReady.Content -and ($responseReady.Content | ConvertFrom-Json).version -eq $selectedChannel.latestVersion) { Write-Host "AppService successfully restarted" -ForegroundColor Green $restartedWebApp = $true break; } } } if ($restartedWebApp) { Write-Host "Go to https://$($appService.hostnames[0]) to upload the Manifest." } else { Write-Error "Restarting of App Service failed. Please try to restart the App Service manually ($appServiceAzureUrl) or try to update Unified Contacts again." } } catch { Write-Error "Something went wrong please. Try again later. Error: $_" -ErrorAction 'Continue' } } |