Я использую шаблон ARM для развертывания Windows ВМ на Azure. В рамках развертывания я хочу выполнить собственный сценарий Powershell
. Скрипт размещен в частном репо на Gitlab
. Для загрузки скрипта я использую токен частного доступа (PAT). Я успешно протестировал загрузку сценария, используя curl
в Bash
, или iwr
в Powershell
, или даже System.Net.WebClient
объект в Powershell
. Однако CustomScriptExtension
не может загрузить файл.
Вот мой Microsoft.Compute/virtualMachines/extensions
ресурс
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(variables('vmName'),'-win', copyindex(), '/installcustomscript')]",
"apiVersion": "2018-06-01",
"location": "[parameters('location')]",
"copy": {
"name": "windowsCount",
"count": "[parameters('numberOfVMs')]"
},
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('vmName'), '-win', copyindex())]"
],
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.10",
"autoUpgradeMinorVersion": true,
"protectedSettings": {},
"settings": {
"fileUris": [
"[if(not(equals(parameters('_artifactsAccessToken'), '')), variables('resourceUriWithToken'), variables('resourceUri'))]"
],
"commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File configure-win-node.ps1"
}
}
}
Формат URI для загрузки скрипта из частного репозитория Gitlab:
TOKEN='xxxxxxxx'
FILE_PATH='path/to/file/configure-win-node.ps1'
# the FILE_PATH is encoded using "uriComponent" ARM template function to satisfy Gitlab's URI format
FILE_PATH_ENCODED="[uriComponent(parameters('FILE_PATH'))]"
PROJECT_ID=13
ASSET_URI="https://gitlab.com/api/v4/projects/${PROJECT_ID}/repository/files/${FILE_PATH_ENCODED}/raw?ref=master&private_token=${TOKEN}"
Закодированный URI выглядит как https://gitlab.com/api/v4/projects/13/repository/files/path%2Fto%2Ffile%2Fconfigure-win-node.ps1/raw?ref=master&private_token=xxxxxxxx
.
Сбой развертывания шаблона ARM на этапе запуска CustomScriptExtension
. В частности, он не может загрузить файл. Вот часть трассировки стека с ошибкой:
[3280+00000001] [07/10/2020 04:27:02.17] [INFO] HandlerSettings = ProtectedSettingsCertThumbprint: 5818102F49DDCA4DDC53367CABB5CDB0DB0AD0F8, ProtectedSettings: {MIIBsAYJKoZIhvcNAQcDoIIBoTCCAZ0CAQAxggFpMIIBZQIBADBNMDkxNzA1BgoJkiaJk/IsZAEZFidXaW5kb3dzIEF6dXJlIENSUCBDZXJ0aWZpY2F0ZSBHZW5lcmF0b3ICEGpZ3BVWIKSCQkYieQ75HmQwDQYJKoZIhvcNAQEBBQAEggEALSb5ZVVbfTAmfkN1U2b7e8+laSZQFuhzIUy/S/S/YK71bDF7JoXI/Ps9Pw9PjAoxS1GLOaEoG+pU5YpvVYlqQR18dug9nBzbmnALGPtQUTC9PqMvk5OneDimmvKBNmAIvXrgnX7D6ELkv3Nkcerud6G2yz7OsfFEEuVlmEk+La27cOmlBZfWBnBkdzRCpINmFzY8EybnCVpIk14aCrBHrOc/544xRPCMKivvtw7RTxJOAAuTiM1aWBtf7FhmNqsmOizkps9+eutmhjEB1WQ8deU7Xd7KJURpmvLjoZc0TeFJ1Kw/u/4SIa59fzuQybtfDDTPa9YvF44nPHTSZrHtWzArBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECDu2Lrirl2CWgAjVJKc65olRCQ==}, PublicSettings: {FileUris: [https://gitlab.com/api/v4/projects/13/repository/files/path%2Fto%2Ffile%2Fconfigure-win-node.ps1/raw?[REDACTED]], CommandToExecute: powershell.exe -ExecutionPolicy Unrestricted -File configure-win-node.ps1}
[3280+00000001] [07/10/2020 04:27:02.41] [INFO] Downloading files specified in configuration...
[3280+00000001] [07/10/2020 04:27:02.53] [INFO] DownloadFiles: fileDownloadPath = C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.9\Downloads\0
[3280+00000001] [07/10/2020 04:27:02.53] [INFO] WebClientDownloader: starting download fileUri = https://gitlab.com/api/v4/projects/13/repository/files/path%2Fto%2Ffile%2Fconfigure-win-node.ps1/raw?[REDACTED]
[3280+00000001] [07/10/2020 04:27:02.80] [WARN] WebClient: non retryable error occurred System.Net.WebException: The remote server returned an error: (404) Not Found.
at System.Net.WebClient.DownloadFile(Uri address, String fileName)
at Microsoft.WindowsAzure.GuestAgent.Plugins.MsiUtils.WebClientWithRetryAbstract.ActionWithRetries(Action action)
[3280+00000001] [07/10/2020 04:27:02.81] [FATAL] Failed to download all specified files. Exiting. Exception: System.Net.WebException: The remote server returned an error: (404) Not Found.
at System.Net.WebClient.DownloadFile(Uri address, String fileName)
at Microsoft.WindowsAzure.GuestAgent.Plugins.MsiUtils.WebClientWithRetryAbstract.ActionWithRetries(Action action)
at Microsoft.WindowsAzure.GuestAgent.Plugins.CustomScriptHandler.Downloader.WebClientDownloader.Download(Uri fileUri, String uriStringForLog, String downloadDir, Msi msi)
at Microsoft.WindowsAzure.GuestAgent.Plugins.CustomScriptHandler.Downloader.DownloadManager.DownloadWithWebClientDownloader(IDictionary`2 uriForDownloadAndLogging, String downloadDir, Msi msi)
at Microsoft.WindowsAzure.GuestAgent.Plugins.CustomScriptHandler.Downloader.DownloadManager.DownloadFiles(IList`1 fileUriStrs, ProtectedSettings protectedSettings, String downloadDir, Boolean isFileUrisProtected)
at Microsoft.WindowsAzure.GuestAgent.Plugins.CustomScriptHandler.Program.Main(String[] args)
[3280+00000001] [07/10/2020 04:27:02.83] [INFO] {"sequenceNumber":0,"totalDuration":1154,"status":"error","code":1,"filesDownloaded":0,"durationOfFileDownload":318,"statusFileAccessed":2,"operation":"enable","operationDuration":86,"operationResult":"success","operationSizeOfOutput":0,"operationSizeOfError":0}
В трассировке стека я не вижу полный URI, поскольку строка запроса помечена как [REDACTED]
. Однако я могу получить полный URI, если перечислю расширения для моей виртуальной машины:
VM_NAME='myVM0'
az vm extension list -g $RG --vm-name $VM_NAME
Вывод, который показывает полный URI, выглядит следующим образом (он отредактирован, чтобы отображать только settings
часть):
"settings": {
"commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File configure-win-node.ps1",
"fileUris": [
"https://gitlab.com/api/v4/projects/13/repository/files/path%2Fto%2Ffile%2Fconfigure-win-node.ps1/raw?ref=master&private_token=xxxxxxxx"
]
},
Если я подключу RDP к виртуальной машине и использую URI из переменной fileUris
в показанном выводе, я могу загрузить сценарий без каких-либо проблем. Вот что я пытался использовать в Powershell
на виртуальной машине:
# download using Invoke-WebRequest cmdlet
iwr -usebasicparsing "https://gitlab.com/api/v4/projects/13/repository/files/path%2Fto%2Ffile%2Fconfigure-win-node.ps1/raw?ref=master&private_token=xxxxxxxx" -outfile configure-win-node.ps1
# download using System.Net.WebClient
(New-Object System.Net.WebClient).DownloadFile("https://gitlab.com/api/v4/projects/13/repository/files/path%2Fto%2Ffile%2Fconfigure-win-node.ps1/raw?ref=master&private_token=xxxxxxxx", "configure-win-node.ps1")
Согласно трассировке стека at System.Net.WebClient.DownloadFile(Uri address, String fileName)
Я использую тот же подход для загрузки скрипта вручную из виртуальной машины. Почему CustomScriptExtension
приводит к (404) Not Found
при попытке загрузить файл с использованием того же URI?
ОБНОВЛЕНИЕ 7/10/2020
Я думаю, проблема может быть связано с тем, как CustomScriptExtension
пытается определить имя файла из URI. Мне удалось обойти проблему загрузки, используя blob-id
вместо filePath
в кодировке URI. Содержимое файла было загружено в файл с именем .\raw
, который является частью URI для получения необработанного содержимого файла из репозитория Gitlab. Вот трассировка стека, показывающая имя файла от выполнения CustomScriptExtension
на виртуальной машине:
[3588+00000001] [07/10/2020 17:01:20.35] [INFO] Downloading files specified in configuration...
[3588+00000001] [07/10/2020 17:01:20.46] [INFO] DownloadFiles: fileDownloadPath = C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.9\Downloads\0
[3588+00000001] [07/10/2020 17:01:20.46] [INFO] WebClientDownloader: starting download fileUri = https://gitlab.com/api/v4/projects/13/repository/blobs/a6339c28f898f3efa620e255d3d8df78abe90503/raw?[REDACTED]
[3588+00000001] [07/10/2020 17:01:20.74] [INFO] WebClientDownloader: Downloaded file to fileDownloadLocation = Downloads\0\raw
[3588+00000001] [07/10/2020 17:01:20.74] [INFO] Files downloaded. Asynchronously executing command: 'powershell.exe -ExecutionPolicy Unrestricted -File configure-win-node.ps1'
Следующая команда Powershell
(т.е. powershell.exe -ExecutionPolicy Unrestricted -File configure-win-node.ps1
) не работает, поскольку такой формат может выполнять только файлы с .ps1
расширение. Обходной путь, который я нашел, заключался в использовании вместо этого Invoke-Command
командлета.
Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Get-Content raw -Raw)))
Я думаю, что одним из решений этой проблемы могло бы быть разрешение пользователю выбирать, под каким именем файла можно сохранить загруженный контент. Другими словами, добавьте параметр к CustomScriptExtension
, чтобы задать имя загружаемого файла.