JayTee
JayTee

Reputation: 486

Powershell command to update azure cloud service (extended support) with files in blob

In the Azure portal, my Cloud Service (Extended Support) gets updated pretty frequently and swapped with another Cloud Service (Extended Support) instance. I have a script that uploads the CSPKG, CSDEF, and CSCFG files to blob storage. This works fine.

I then go to the portal, find the instance I want to update, click Update, change to Blob storage, browse to the files I uploaded and click on the update button. This kicks off the process and about 7-9 minutes later the instance is ready to use.

I am trying to replicate this update process in PowerShell, and though it appears that it works, the instance never actually updates. It finds the cloud service just fine. This is what I have put together:

    # Get an SAS token to CSPKG
    Write-Host ("$(Get-Date -f $timeStampFormat) Getting CSPKG Shared Access Signature (SAS) token") -ForegroundColor DarkCyan 
    #$tokenStartTime = Get-Date
    #$tokenEndTime = $tokenStartTime.AddYears(1)
    #$cspkgToken = New-AzStorageBlobSASToken -Container “vs-deploy” -Blob “MyCloudService.cspkg” -Permission rwd -StartTime $tokenStartTime -ExpiryTime $tokenEndTime -Context $storageAccount.Context 

$cloudService = (Get-AzCloudService) |
    Where-Object {
        $_.networkProfile.LoadBalancerConfiguration.FrontendIPConfiguration.PublicIPAddressId -like "*MyIP"
    }    
$stagingServiceName = $cloudService.Name

    Write-Host ("$(Get-Date -f $timeStampFormat) Deploying to {0} Cloud Service" -f $stagingServiceName) -ForegroundColor DarkCyan

# Load the CSCFG XML into a string from local drive
$cscfgContent = Get-Content $cscfgFilePath | Out-String

 try {
        Write-Host "URI for blob: "$cspkgBlob.ICloudBlob.Uri.AbsoluteUri
        # Update the cloud service
        $cloudService.PackageUrl = $cspkgBlob.ICloudBlob.Uri.AbsoluteUri
        $cloudService.Configuration = $cscfgContent
        $cloudService | Update-AzCloudService
    } catch {
        Write-Host ("$(Get-Date -f $timeStampFormat) Cloud Service {0} failed to update: {1}" -f $service, $_.Exception.Message) -ForegroundColor Red
        break;
    }

Write-Host ("$(Get-Date -f $timeStampFormat) Finished")

First question is: Why is there no mention of the CSDEF file when the portal requires it to update?

Second question: One of the methods I tried required the SAS token but this one doesn't seem to. Did I miss something?

Third question: I could not find a way to read the CSCFG file from the blob to resorted to reading it from my local drive. What is the proper way to get it from the blob?

Final question: Even though this appears to update, the instance doesn't change. What am I missing?

Thanks, JayTee

Upvotes: 2

Views: 478

Answers (2)

Greig Stewart
Greig Stewart

Reputation: 119

I've encountered the same issue - although the Update-AzCloudService command reports a success, the instance does not update with the new code. I've also tried re-imaging and resetting the instance with no luck. Update-AzCloudService does not seem to be fit for purpose with respect to updating Extended Support cloud services. I have contacted Microsoft regarding this but have not reached a conclusion.

My solution was the following:

  1. Deploy first via VS and download the template of the successful ARM deployment - this will give you template.json and parameters.json
  2. Upload the new cspkg and cscfg files to blob storage and retrieve a SAS token link for each.
  3. Use the ARM Template deployment task in DevOps with the action set to "Create or update resource group" and deployment mode set to "Incremental" and override the packageSasUri and configurationSasUri parameters with the SAS urls from (2). Use the template and parameter files from (1).

Note that the DevOps task can most likely be replicated in powershell, but I haven't had the time to do that yet. For reference the DevOps task code is here.

Optional: To automate (2) you can use the following in an Azure Powershell Devops task, and then reference the output variables in the ARM template deployment parameter overrides..

Install-Module -Name Az.Storage  -Repository PSGallery -Force -AllowClobber

$cspkgFilePath = "<PATH TO cspkg>"
$cspkgBlobPath = $env:BUILD_BUILDNUMBER + "/package.cspkg"
$cscfgFilePath = "<PATH TO cscfg>"
$cscfgBlobPath = $env:BUILD_BUILDNUMBER + "/ServiceConfiguration.Cloud.cscfg"

$storageAccount = Get-AzStorageAccount -ResourceGroupName "<resouce group name>" -Name "<storage account name>"

$tokenStartTime = Get-Date 
$tokenEndTime = $tokenStartTime.AddDays(1) 
$cspkgBlob = Set-AzStorageBlobContent -File $cspkgFilePath -Container "vsdeploy" -Blob $cspkgBlobPath -Context $storageAccount.Context -Force
$cspkgToken = New-AzStorageBlobSASToken -Container "vsdeploy" -Blob $cspkgBlob.Name -Permission rwd -StartTime $tokenStartTime -ExpiryTime $tokenEndTime -Context $storageAccount.Context 
$cspkgUrl = $cspkgBlob.ICloudBlob.Uri.AbsoluteUri + "?" + $cspkgToken 

$cscfgBlob = Set-AzStorageBlobContent -File $cscfgFilePath -Container "vsdeploy" -Blob $cscfgBlobPath -Context $storageAccount.Context -Force
$cscfgToken = New-AzStorageBlobSASToken -Container "vsdeploy" -Blob $cscfgBlob.Name -Permission rwd -StartTime $tokenStartTime -ExpiryTime $tokenEndTime -Context $storageAccount.Context 
$cscfgUrl = $cscfgBlob.ICloudBlob.Uri.AbsoluteUri + "?" + $cscfgToken 

$cspkgUrl
$cscfgUrl
Write-Host "##vso[task.setvariable variable=cspkgUrl;isOutput=true]$cspkgUrl"
Write-Host "##vso[task.setvariable variable=cscfgUrl;isOutput=true]$cscfgUrl"

Upvotes: 0

Greg D
Greg D

Reputation: 44086

I suspect you'll get the most value from the Cloud Services - Create Or Update docs. Create and Update are the same operation in the world of Cloud Services (Extended Support).

  1. I'm not sure why Portal wants the CSDEF. I don't see a requirement for it in the raw REST API.
  2. You can provide either the raw CSCFG or a SAS URI to your CSCFG per the REST docs. You can supply the raw CSCFG via configuration (as you're doing above) or you can supply a SAS URI via configurationUrl. (It does look like the docs have a typo there- The second sentence of configurationUrl should read "The service package configuration URL can be....")
  3. See #2. You can use the SAS URI for your CSCFG blob by using the configurationUrl instead of configuration in the CloudServiceProperties.
  4. I don't think we have enough information here. Consider double-checking that you're providing the expected new package and configuration and not accidentally providing the old one?

Upvotes: 0

Related Questions