在托管 2017 代理上升级 AzureRM Powershell(VSTS - Visual Studio 团队服务)

Upgrade AzureRM Powershell on Hosted 2017 Agent (VSTS - Visual Studio Team Services)

我正在通过 Visual Studio Teams Services(在线)使用发布管理。我们使用托管构建代理,我真的想避免管理自定义代理的开销。

我确实需要的一项是 AzureRM PowerShell 模块。 5.1.1 之前的版本是 available on the agent,但我需要 6.0.0。

我想做的是在我的发布过程 (PowerShell) 中使用一个步骤来获取版本 6.0.0 并改用 thart,但是我无法让它正常工作。我尝试了几种方法都失败了,目前的方法是:

Write-Output "------------------ Install package provider ------------------"
Find-PackageProvider -Name "NuGet" | Install-PackageProvider -Scope CurrentUser -Force

Write-Output "------------------ Remove Modules ------------------"
Get-Module -ListAvailable | Where-Object {$_.Name -like 'AzureRM*'} | Remove-Module

Write-Output "------------------ Install the AzureRM version we want - 6.0.1!  ------------------"
Install-Package AzureRM -RequiredVersion 6.0.1 -Scope CurrentUser -Force

Write-Output "------------------ Import AzureRM 6.0.1  ------------------"
Import-Module AzureRM -RequiredVersion 6.0.1

这一切工作正常(即不会崩溃...)但是当我尝试使用 6.0.1 cmdlet 之一时我收到错误。

Get-AzureRmADGroup : The Azure PowerShell session has not been properly initialized. Please import the module and try again.

知道我哪里出错了或者我可以用来部署 AzureRM 6.0.1 并在托管代理上使用它的替代策略吗?

我终于弄明白了 - 为其他遇到同样问题的人添加了一个答案。

关键是AzureRM模块升级后登录。

PowerShell 代码:

    Write-Output "------------------ Start: Upgrade AzureRM on build host ------------------"

    Write-Output "- - - - - Install package provider"
    Install-PackageProvider -Name NuGet -Force -Scope CurrentUser

    Write-Output "- - - - - List Modules Before"
    Get-Module -ListAvailable| where {$_.Name -Like “*AzureRM*”}  | Select Name, Version

    Write-Output "- - - - - Remove alll existing AzureRM Modules" 
    Get-Module -ListAvailable | Where-Object {$_.Name -like '*AzureRM*'} | Remove-Module -Force 

    Write-Output "- - - - - Install AzureRM 6.0.1"
    Install-Module -Name AzureRM -RequiredVersion 6.0.1 -Force -Scope CurrentUser

    Write-Output "- - - - - Import AzureRM 6.0.1"
    Import-Module AzureRM -Force -Verbose -Scope Local

    Write-Output "- - - - - List Modules After"
    Get-Module -ListAvailable| where {$_.Name -Like “*AzureRM*”}  | Select Name, Version

    Write-Output "------------------ End: Upgrade AzureRM on build host ------------------"

    Write-Output "------------------ Start: LoginToAzure ------------------"

    $SecurePassword = ConvertTo-SecureString $AdminPassword -AsPlainText -Force
    $AdminCredential = New-Object System.Management.Automation.PSCredential ($AdminUserEmailAddress, $SecurePassword)
    Login-AzureRmAccount -Credential $AdminCredential

    Get-AzureRmSubscription –SubscriptionId $SubscriptionId | Select-AzureRmSubscription

    Write-Output "------------------ End: LoginToAzure ------------------"

感谢 Murray 指出了正确方向的初始点,展示了我希望做的事情并非不可能!

我最初尝试在 Azure PowerShell 任务中执行此操作并取得了相当大的进展,但遇到了死胡同 AzureRm.Profile as you cannot unload an old version

诀窍是理解 AzureRM VSTS 任务如何进行依赖设置,它有效地获取 VSTS UI 中的 "Azure Powershell Version" 字符串并使用它在 PSModules 中定义额外的搜索路径环境变量即 C:\Modules\azurerm_5.1.1.

它将在该目录中查找,在搜索用户配置文件之前,然后是全局模块路径。

一旦找到模块,它就会执行 Azure 登录,这将阻碍之后删除模块的任何希望。

因此,如果您改为使用普通的 powershell 任务,即未加载 AzureRM 的任务(正如 Murray 还得出的结论):

Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
Install-Module -Name AzureRM -RequiredVersion 6.2.1 -Force -Scope CurrentUser -AllowClobber

值得注意的是,安装模块不会像 vsts image generation project.

那样安装到 c:\modules

我似乎需要 AllowClobber 来解决在试验时覆盖旧 powershell 版本的问题,但我怀疑我不再需要它了。

优雅的解决方案在下次使用 Azure PowerShell 脚本时启动。

首选的 powershell 版本字段填写 6.2.1 将添加 C:\Modules\azurerm_6.2.1 到 PSModules 路径。这不存在,但值得庆幸的是因为 PSModules 仍然包含用户特定的模块路径,所以我们的 6.2.1 是自己加载的!

幸运的是,来自 5.1.1 的 AzureRM.Profile 具有足够的向前兼容性,Azure Powershell 任务执行的服务主体登录仍然有效。

运行

Get-Module AzureRm 
Get-AzureRmContext

将输出您希望的版本:

特别是如果它无法登录,我 认为 System.AccessToken 可以使用(如果在代理阶段级别打开该选项)。

诊断技术(如果解决方法需要调整):

阅读在任务中加载到 AzureRM 中的代码非常有帮助:

https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/AzurePowerShellV3/AzurePowerShell.ps1#L80

https://github.com/Microsoft/vsts-tasks/blob/0703b8869041d64db994934bde97de167787ed2e/Tasks/Common/VstsAzureHelpers_/ImportFunctions.ps1

https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/AzurePowerShellV3/Utility.ps1#L18

以及 VSTS 图像的生成方式:

https://github.com/Microsoft/vsts-image-generation/blob/2f57db26dc30ae0f257a3415d26eaa8eea0febf9/images/win/scripts/Installers/Install-AzureModules.ps1

启用 System.Debug = true 作为环境发布变量。 然后使用 VSCode's Log File Highlighter plugin


我鼓励任何有兴趣的人投票https://github.com/Microsoft/vsts-image-generation/issues/149

由于撰写本文时的 AzureRM 版本在 VSTS Hosted 2017 代理上已经过时。

不幸的是,我无法提交 PR 来升级它,因为它是通过私人托管的 zip 文件引入的。