Автоматизация задач с помощью PowerShell PSake: Подробное руководство

Итак, вы научились автоматизировать задачи с помощью сценариев PowerShell.
Это замечательно! Но теперь у вас есть беспорядок из сценариев и модулей, смешанных вместе с ручным выполнением сценариев, запланированными заданиями и так далее. Пришло время привести некоторый порядок в этот хаос и внедрить средство оркестрации автоматизации, известное как PowerShell PSake.

PSake – это средство оркестрации, написанное в виде модуля PowerShell, которое придает порядок вашим сценариям и дает вам полный контроль над тем, что и когда выполняется при каких условиях. Хотя PSake является средством автоматизации сборки и его основное применение – это сценарии сборки (обычно выполняемые сборочным сервером в сценариях автоматизации выпуска), он обычно игнорируется в повседневных сценариях сценаризации. Давайте это изменить.

В этом руководстве вы узнаете, как работает PSake, а также получите несколько отличных примеров, которые вы можете применить уже сегодня!

Предварительные требования

Эта статья будет учебным пособием, ожидая, что вы будете следовать инструкциям. Если вы хотите следовать точно так же, как описано, убедитесь, что у вас есть:

  • Windows PowerShell 3+. В учебнике используется Windows PowerShell v5.1
  • Файл PSake zip с Github. В этом учебнике используется версия 4.9.0.

Настройка модуля PSake

Предполагая, что у вас есть проект PSake из GitHub на вашем локальном компьютере, вам сначала нужно выполнить несколько шагов для его настройки.

  1. Распакуйте загруженный с GitHub zip-файл PSake.
  2. Переместите папку src внутри распакованных файлов ZIP по пути под $env:PSModulePath, чтобы обеспечить доступ к новому модулю в PowerShell.
  3. Переименуйте папку src в PSake.
  4. Теперь выполните команду Get-Module PSake -ListAvailable , чтобы убедиться, что модуль отображается. Если ошибок нет, можно продолжать.

Связано: Понимание и создание модулей PowerShell

Создание простого сценария PowerShell PSake

Чтобы понять PSake, нужно что-то создать. Давайте создадим простой сценарий PSake, чтобы увидеть, что он может делать.

  1. Создайте сценарий с именем psakefile.ps1 с одним заданием. Как минимум, задание должно иметь имя и блок действий. Имя psakefile.ps1 необязательно, но оно является ожидаемым именем по умолчанию для движка.

A PSake task in its basic form is very similar to a PowerShell function:
a container for one or more commands that, when performed together, achieve a certain goal. These commands go into a script block that is passed to the Action parameter. A task has many advantages over a function. You will learn about these advantages as you read along.

Ниже пример psakefile.ps1 с довольно простым заданием:

task HelloWorld -Action {
    Write-Host '*** Hello World ***' -ForegroundColor Yellow
}

2. Теперь, когда вы создали файл PSake, вы можете вызвать его из консоли PowerShell с помощью команды Invoke-PSake и передать имя задания как значение параметра TaskList .

Invoke-PSake – это исполнительный движок для PSake. Эта команда запускает задачи, определенные в файле psakefile.ps1. Вы передаете имя задачи или список задач, разделенных запятыми, параметру TaskList. Если вы выполняете несколько задач, каждая задача будет выполняться в порядке, в котором вы их передали в TaskList, независимо от их расположения в файле psakefile.ps1.

Вот как вы можете запустить задачу HelloWorld:

Invoke-PSake -BuildFile C:\Work\psakefile.ps1 -TaskList 'HelloWorld'

Пока вы сохраняете имя psakefile.ps1 и устанавливаете консоль в каталог, где он находится, вы можете опустить параметр BuildFile и его значение.

  1. Запуск Invoke-PSake покажет вывод PSake в консоли. При выполнении задач в файле psakefile.ps1 вы увидите вывод, аналогичный тому, что вы видите ниже.
Psake script output

Вывод состоит из следующих компонентов:

  1. Сведения о версии PSake.
  2. Имя каждой сборочной задачи прямо перед ее выполнением (PSake рассматривает каждую задачу как сборочную задачу). В примере: Выполняется HelloWorld в голубом цвете.
  3. Любой вывод, который произвела задача. В примере: Привет, мир желтого цвета.
  4. Сообщение об успехе/неудаче. В примере: psake выполнен успешно… зеленого цвета.
  5. Сводка времени (названная Отчет о времени сборки) с продолжительностью каждой задачи, а также общей продолжительностью всего скрипта.

Установка SQL с помощью PSake

В предыдущем разделе вы не сделали ничего, кроме как вызвали фиктивный сценарий PSake. Теперь продолжите на основе этого знания и создайте сценарий PSake, который устанавливает SQL!

В этом примере вы создадите скрипт PSake, который:

  1. Проверяет наличие свободного места на диске у компьютера.
  2. Загружает файл ZIP SQL из локального репозитория.
  3. Распаковывает ZIP-файл.
  4. Запускает установку на диске C или D (на том из двух, который существует).

Давайте посмотрим, как мы можем использовать PSake для выполнения этой работы.

Проектирование строительных блоков

PSake предназначен для оркестрации задач. Каждая задача должна иметь уникальное имя и, в идеале, должна выполнять отдельную атомарную операцию, например, функцию PowerShell. Используя эту концепцию, вы можете описать следующие шаги для создания задачи для каждой из них.

  1. ValidateDiskSpace
  2. DownloadSql
  3. ExtractSql
  4. InstallSqlDriveC
  5. InstallSqlDriveD

На этом этапе вы фактически не создаете код для выполнения каких-либо действий; вы просто создаете каркас задач и создаете файл PSake. Вы заметите ссылки Write-Host в задачах ниже; вы добавите к задачам позже.

Всегда следует использовать параметр Description для каждой задачи. Параметр Description предоставляет дополнительную информацию о каждой задаче при выполнении задач и при просмотре кода.

task ValidateDiskSpace -Description 'Validate Disk Free Space' -Action {
	
	Write-Host "`n   *** Checking disk free space ***`n" -ForegroundColor Yellow
	
}

task DownloadSql -Description 'Download SQL Setup' -Action {
	
	Write-Host "`n   *** Downloading SQL Setup from LAN ***`n" -ForegroundColor Yellow
	
}

task ExtractSql -Description 'Extract SQL Setup' -Action {
	
	Write-Host "`n   *** Extracting SQL Setup files ***`n" -ForegroundColor Yellow
	
}

task InstallSqlDriveC -Description 'Install SQL on C:' -Action {
	
	Write-Host "`n   *** Installing SQL Server on C drive ... please wait... ***`n" -ForegroundColor Yellow

}

task InstallSqlDriveD -Description 'Install SQL on D:' -Action {
	
	Write-Host "`n   *** Installing SQL Server on D drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

Определение порядка выполнения задач

Теперь у вас есть файл PSake, содержащий набор задач. В этой точке вы можете выполнить все задачи сразу или выбрать, чтобы выполнить только некоторые из них с помощью команды Invoke-PSake.

Вы можете вызывать некоторые (или все задачи), используя Invoke-PSake и параметр TaskList, как вы делали ранее в простом примере. Если у вас есть более одной задачи для вызова, создайте массив и определите имя каждой задачи как элемент, как показано ниже.

Invoke-PSake будет выполнять каждую задачу в порядке, определенном в массиве.

$taskList = @()

$taskList += 'ValidateDiskSpace'
$taskList += 'DownloadSql'
$taskList += 'ExtractSql'
$taskList += 'InstallSqlDriveC'
$taskList += 'InstallSqlDriveD'

Invoke-PSake -TaskList $taskList

При запуске вышеприведенного кода вы должны получить результат, подобный следующему:

PSake script output

Добавление предусловия

Возможно, вам нужно выполнить некоторое действие только если определенное условие выполняется. В примере сценария установки SQL, возможно, вам нужно проверить, доступен ли том, на котором хранится установщик, перед выполнением задачи для вызова этого установщика.

Вы можете использовать параметр PreCondition для выполнения фрагмента кода, который возвращает значение True или False, которое определяет, выполняется ли эта задача или нет.

Обратите внимание на пример ниже переменные $installSqlOn_C_Drive и $installSqlOn_D_Drive. Когда Invoke-PSake вызывает этот сценарий, эти переменные будут содержать значение True или False в зависимости от того, существует ли том C или D.

На каждой строке task вы можете видеть, что у каждой задачи есть параметр PreCondition scriptblock, который содержит значение этих переменных. Во время выполнения будет выполняться либо задача InstallSqlDriveC, либо задача InstallSqlDriveD, в зависимости от этих переменных.

$installSqlOn_C_Drive = (Test-Path -Path 'C:') -and (-not (Test-Path -Path 'D:'))
$installSqlOn_D_Drive = (-not (Test-Path -Path 'C:')) -and (Test-Path -Path 'D:')

task InstallSqlDriveC -Description 'Install SQL on C:' -PreCondition { $installSqlOn_C_Drive } -Action {
	
	Write-Host "`n   *** Installing SQL Server on C drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

task InstallSqlDriveD -Description 'Install SQL on D:' -PreCondition { $installSqlOn_D_Drive } -Action {
	
	Write-Host "`n   *** Installing SQL Server on D drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

Параметры задачи

В дополнение к Action и Description, задача также поддерживает следующие параметры:

  • PreCondition – Скриптовый блок, возвращающий логическое значение. При значении False конкретная задача пропускается. (Пример использования показан выше).
  • PostCondition Шаг проверки. Скриптовый блок, возвращающий логическое значение. False означает, что проверка не пройдена и весь скрипт останавливается.
  • PreAction – Скриптовый блок, который выполняется перед выполнением задачи.
  • PostAction Скриптовый блок, который выполняется сразу после успешного завершения задачи.
  • ContinueOnError Переключатель. При использовании не прерывает выполнение всего скрипта при возникновении ошибок во время выполнения задачи.
  • Depends Название задачи (или список названий задач), которая должна быть выполнена перед текущей задачей. PSake использует эту информацию для выполнения зависимостей задач в правильном порядке. Например, если задача A зависит от задачи B, то PSake выполнит B перед A.

На первый взгляд механизм зависимостей кажется хорошей идеей. Он помогает установить задачи в логическом порядке. Однако использование параметра Depends объединяет различные задачи, что затрудняет их независимое тестирование. Однако, поскольку пользователь может явно установить порядок выполнения задач и передать этот порядок при вызове файла PSake → использование параметра Depends вообще можно избежать.

Давайте рассмотрим пример использования некоторых из этих параметров задачи:

Добавление предварительного действия и послерейсового условия

Используя задачу InstallSqlDriveD из приведенного выше примера как отправную точку, возможно, у вас есть дополнительный запрос к установке.

Возможно, вам нужно записать времена начала и завершения установки. Вам нужно записать эти времена в две переменные среды с именами SqlSetupStartDate и SqlSetupEndDate. Во-вторых, после завершения установки, вам нужно проверить, что папка D:\TempSqlFiles не существует.

К счастью, параметры задач PSake PreAction, PostAction и PostCondition (соответственно) точно соответствуют этим новым требованиям. Вот пример того, как это может быть сделано:

task InstallSqlDriveD -Description 'Install SQL on D:' -PreAction {

     Write-Host '*** Writing SQL install start time to env. var. SqlSetupStartDate ***' -ForegroundColor Yellow
     $date = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
[Environment]::SetEnvironmentVariable('SqlSetupStartDate',$date,'Machine')

 } -PreCondition { 

     $installSqlOn_D_Drive

 } -Action {  
  
     Write-Host '*** Installing SQL Server on D drive... please wait... ***' -ForegroundColor Yellow 

} -PostAction {     

    Write-Host '*** Writing SQL install end time to env. var. SqlSetupEndDate ***' -ForegroundColor Yellow     
    $date = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
[Environment]::SetEnvironmentVariable('SqlSetupEndDate',$date,'Machine') 

} -PostCondition { 
    
Write-Host '*** Verifying temp files deleted ***' -ForegroundColor Yellow
     # в случае, если папка существует, это вернет False, вызывая остановку всего сценария
     (-not (Test-Path -Path 'D:\TempSqlFiles'))

 }

Запуск сценариев PSake в тестах Pester

Где бы вы ни могли вызвать сценарий PowerShell, вы можете вызвать файл PSake. Если вы создаете тесты для инфраструктуры с Pester, вы можете вызвать PSake в тестах.

Связано: Написание тестов Pester для PowerShell

Например, возможно, у вас есть тест Pester для подтверждения наличия файла ZIP установки SQL в папке после выполнения задачи DownloadSql. В этом случае вы создаете простой тест Pester и вызываете задачу DownloadSql внутри теста, а затем проверяете наличие файла ZIP сразу после его выполнения.

Describe 'SQL install with PSake' {

    It 'Downloads Sql files' {

        $setup = 'C:\Downloads\SqlSetup.zip'

        if(Test-Path -Path $setup)
        {
            Remove-Item -Path $setup
        }

        # единственная задача под тестом здесь - DownloadSql
        Invoke-PSake -BuildFile C:\Work\psakefile.ps1 -TaskList DownloadSql
        
        $setup | Should -Exist
    }
}

Передача параметров задачам

Когда вы начинаете использовать PSake, вам может потребоваться параметризовать некоторые из задач. Обычно, с функциями и сценариями PowerShell, вы передаете различные именованные параметры в функцию/сценарий; PSake работает по-другому.

Чтобы передать параметры в файлы PSake, вы можете использовать блок Properties, который определяет пары ключ/значение, которые PSake затем делает доступными внутри каждой задачи в файле.

Обязательно определите блок Properties в верхней части файла PSake. Все операции PSake читаются сверху вниз.

Например, чтобы передать динамические переменные SqlYear и SqlVersion каждой задаче в файле PSake, вы можете определить их, как показано ниже.

Properties {
    $SqlYear = '2017'
    $SqlVersion = '14.0'
}

task -Name DownloadSql -Action {
    
    Write-Host "SQL version to install: SQL $SqlYear (version $SqlVersion)"

}

Затем, когда вы вызываете файл PSake с помощью Invoke-PSake, вы увидите следующий вывод. Обратите внимание, что переменные $SqlYear и $SqlVersion были расширены значениями, определенными в блоке Properties.

psake version 4.9.1
Copyright (c) 2010-2018 James Kovacs & Contributors

Executing DownloadSql
SQL version to install: SQL 2017 (version 14.0)

psake succeeded executing C:\Work\PSakefile.ps1

--------------------------------------------------
Build Time Report
--------------------------------------------------

Name        Duration
----        --------
DownloadSql 00:00:00
------      --------
Total:      00:00:00

Использование параметра Properties

Если вы предпочитаете передавать параметры задаче через традиционный параметр, PSake может помочь. Вам все равно нужно оставить блок Properties в верхней части psakefile.ps1, как в приведенном выше примере, но PSake позволяет вам переопределить значения.

Чтобы сделать это, определите хэш-таблицу с каждой парой ключ/значение, которую вы хотите переопределить. Затем передайте хэш-таблицу в параметр Properties. Движок PSake будет использовать значения из переданной хэш-таблицы вместо тех, которые указаны в блоке Properties внутри скрипта psakefile.ps1.

Обратите внимание на различия в синтаксисе между блоком Properties и параметром Properties. В блоке Properties каждая строка – это переменная и, следовательно, предварительно указана знаком доллара, тогда как параметр Properties – это хэш-таблица, поэтому каждый элемент – это ключ и записан без ведущего $. Еще одним отличием является то, что хэш-таблица предваряется символом @.

Ниже приведен пример использования параметра Properties.

$myNewProperties = @{
    SqlYear = '2019'
    SqlVersion = '15.0'
}

Invoke-PSake -TaskList DownloadSql -Properties $myNewProperties

Модуль PSake Task: Задачи как файлы

В какой-то момент ваш файл PSake, вероятно, будет расти экспоненциально, особенно если вам нужно оркестрировать большие задачи автоматизации. Чтобы обеспечить возможность управления всеми этими задачами, стоит сосредоточиться на модульности или разделении задач для упрощения управления.

Связано: Как выжить при рефакторинге сценария PowerShell из ада

В примере этого учебного пособия вы работали с пятью задачами:

  • ValidateDiskSpace
  • DownloadSql
  • ExtractSql
  • InstallSqlDriveC

Каждая из этих задач определена внутри одного сценария pssakefile.ps1. Если вы предполагаете, что с течением времени добавится еще много задач, вам следует разделить эти задачи на отдельные файлы, где каждая задача будет внутри, например, ValidateDiskSpace.ps1, DownloadSql.ps1, InstallSqlDriveD.ps1, InstallSqlDriveD.ps1 и т. д.

Например, InstallSqlDriveD.ps1 будет содержать только этот код:

task InstallSqlDriveD -Description 'Install SQL on D:' -PreCondition { $installSqlOn_D_Drive } -Action {
	
	Write-Host "`n   *** Installing SQL Server on D drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

Как только задачи будут вынесены, импортируйте файлы в psakefile.ps1, используя функцию Include. Когда это сделано, содержание psakefile.ps1 сокращается до этого кода:

$installSqlOn_C_Drive = $true
$installSqlOn_D_Drive = $false

Include "$PSScriptRoot\ValidateDiskSpace.ps1"
Include "$PSScriptRoot\DownloadSql.ps1"
Include "$PSScriptRoot\ExtractSql.ps1"
Include "$PSScriptRoot\InstallSqlOnC.ps1"
Include "$PSScriptRoot\InstallSqlOnD.ps1"

Когда Invoke-PSake запускает сценарий psakefile.ps1, Invoke-PSake не знает и не обращает внимания на то, находятся ли задачи внутри файла psake или были импортированы с помощью метода Include.

Следующие шаги

PSake – мощный скриптовый оркестратор, который может использоваться для множества целей: сборки программного обеспечения, CI/CD, развертывания пакетов, создания установщиков и многое другое. Единственное ограничение – ваше воображение. Привыкание к созданию больших скриптов с помощью PSake заставляет вас думать в терминах задач (кодовых блоков). Концепция задач использует синтаксис PowerShell, и, используя задачи, вы обогащаете свои знания командной строки.

Код, который вы создаете с помощью PSake, становится более читаемым, поддерживаемым и легче тестировать. После некоторой практики вы обнаружите, что разделение шагов на разные задачи делает их более легкими для написания. Небольшое количество дополнительной работы окупается большими результатами в среднесрочной и долгосрочной перспективе.

Где вы видите применение PSake в своих проектах?

Source:
https://adamtheautomator.com/powershell-psake/