Возможно ли иметь функцию модуля, которая изменяет значения параметров скрипта вызывающей стороны? - PullRequest
0 голосов
/ 02 мая 2019

Мотивация

Уменьшите объем обслуживания задачи DevOps Azure, которая вызывает скрипт Powershell с большим количеством параметров («много» может быть 5).

Идея основана на том факте, что AzOv DevOps генерирует переменные среды для отражения переменных сборки.Итак, я разработал следующую схему:

  1. Префикс всех несекретных переменных DevOps Azure с MyBuild.
  2. Сценарий PowerShell для задачи вызовет функцию для проверки параметров сценария на соответствие MyBuild_ переменных среды и автоматически назначит значение переменной среды MyBuild_xyz параметру сценария xyz, если последний не имеет значения.

Таким образом, командная строка задачи будет содержать только секретпараметры (которые не отражаются в окружающей среде).Зачастую секретных параметров нет, поэтому командная строка остается пустой.Мы находим эту схему, чтобы уменьшить обслуживание задач, управляемых сценарием powershell.

Пример

param(
    $DBUser,
    [ValidateNotNullOrEmpty()]$DBPassword,
    $DBServer,
    $Configuration,
    $Solutions,
    $ClientDB = $env:Build_DefinitionName,
    $RawBuildVersion = $env:Build_BuildNumber,
    $BuildDefinition = $env:Build_DefinitionName,
    $Changeset = $env:Build_SourceVersion,
    $OutDir = $env:Build_BinariesDirectory,
    $TempDir,
    [Switch]$EnforceNoMetadataStoreChanges
)

$ErrorActionPreference = "Stop"

. $PSScriptRoot\AutomationBootstrap.ps1
$AutomationScripts = GetToolPackage DevOpsAutomation

. "$AutomationScripts\vNext\DefaultParameterValueBinding.ps1" $PSCommandPath -Required 'ClientDB' -Props @{
    OutDir = @{ DefaultValue = [io.path]::GetFullPath("$PSScriptRoot\..\..\bin") }
    TempDir = @{ DefaultValue = 'D:\_gctemp' }
    DBUser = @{ DefaultValue = 'SomeUser' }
}

Описанная логика привязки параметров реализована в сценарии DefaultParameterValueBinding.ps1 , которая публикуется в пакете NuGet.Код устанавливает пакет и, таким образом, получает доступ к сценарию.

В приведенном выше примере некоторые параметры по умолчанию предопределены переменными Azure Devops, такими как $RawBuildVersion = $env:Build_BuildNumber.Некоторые остаются неинициализированными, например $DBServer, что означает, что по умолчанию будет $env:MyBuild_DBServer.

. Мы можем обойтись без специальной функции для связывания, но тогда автор сценария должен будет написать что-то вродеэто:

$DBServer = $env:MyBuild_DBServer,
$Configuration = $env:MyBuild_Configuration,
$Solutions = $env:MyBuild_Solutions,

Я хотел избежать этого из-за возможности случайного несоответствия имени.

Проблема

Подход делаетне работает, когда я упаковываю логику DefaultParameterValueBinding.ps1 в функцию модуля.Это связано с изоляцией области видимости модуля - я просто не могу изменить параметры скрипта вызывающего абонента.

Возможно ли это сделать?Можно ли достичь своей цели более элегантным способом?Помните, я хочу сократить расходы, связанные с обслуживанием командной строки задачи в DevOps Azure.

Сейчас я склонен вернуться к этой схеме:

$xyz = $(Resolve-ParameterValue 'xyz' x y z ...)

Где Resolve-ParameterValue сначала проверит $env:MyBuild_xyz и, если не найден, выберет первое ненулевое значение из x, y, z, ...

Но если метод Resolve-ParameterValue поступает из модуля, сценарий должен предположить, что модуль уже установлен, поскольку он не может установить его до того, как параметрыоценены.Или он есть?

EDIT 1

Обратите внимание на командную строку, используемую для вызова сценария DefaultParameterValueBinding.ps1 , который не содержит параметров сценария вызывающей программы!Он включает $PSCommandPath, который используется для получения коллекции PSBoundParameters.

1 Ответ

1 голос
/ 02 мая 2019

Да, но это потребует внесения изменений в вызывающий скрипт и функцию. Передайте параметры по ссылке. У Адама Б. есть хорошая статья о передаче параметров по ссылке:

https://mcpmag.com/articles/2015/06/04/reference-variables-in-powershell.aspx

Net-net, следующий пример:

$age = 12;

function birthday {
  param([ref]$age)
  $age.value += 1
}

birthday -age ([ref]$age)

Write-Output $age

У меня 12 лет. Я передаю его в функцию в качестве параметра. Функция увеличивает значение $ age на 1. Вы можете сделать то же самое с функцией в модуле. Вы меня поняли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...