OpenQuality.ru

Качество программного обеспечения

Сервисы в Azure: автоматизация развертывания

Добрый день.

Как уже отмечалось ранее, Windows Azure представляет собой облачную операционную систему, реализующую парадигму PaaS: разработчик получает платформу (API) для создания информационных систем и место для их размещения. Практически любая информационная система строится из кирпичиков двух типов: сервис и хранилище данных. Если создание хранилищ в Azure – зачастую однократная операция, то сервисы обновляются постоянно (внесение новой функциональности, исправление багов). Обновлять сервисы в Azure можно через web-интерфейс, но это не всегда удобно. Почему?

Предпосылки для автоматизации и постановка задачи

В Azure большие системы обычно представлены, как минимум, в трех лицах (имена условны): Live (c ней работают пользователи), Test (пространство для тестирования) и Dev (разработка). Далее, более-менее серьезная система состоит из нескольких сервисов, каждый из которых выполняет свою функцию. Например, обработка входного трафика, базовый функционал, web-интерфейс и т.п. И, наконец, в каждом пространстве для сервисов есть слоты Production и Staging – для более удобной отладки и минимизации простоя системы при переходе с одной версии на другую. Каждый сервис представлен, как минимум, двумя файлами: программный код в виде бинарного пакета (*.cspkg) и текстовый конфигурационный файл (*.cscfg). Содержимое конфигурационного файла меняется в зависимости от места разрмещения сервиса и его настроек.

Задача: автоматизировать внесение изменений в конфигурационные файлы и развертывание сервисов в облаке.

Работа с конфигурационными файлами

Конфигурационный файл для сервиса может выглядеть так:

<?xml version="1.0"?>
<ServiceConfiguration serviceName="YourServiceName" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="Controller">
    <Instances count="5" />
    <ConfigurationSettings>
      <Setting name="keepalive" value="true" />
      <Setting name="Storage" value="StorageName:::StorageAccessKey"/>
      <Setting name="Logs" value="LogLocation:::LogAccessKey"/>
    </ConfigurationSettings>
  </Role>
  <Role name="BasicFunctions">
    <Instances count="3" />
    <ConfigurationSettings>
      <Setting name="Connections" value="ConnNumber" />
      <Setting name="Storage" value="StorageName:::StorageAccessKey"/>
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

Одни параметры могут оставаться неизменными для любого варианта развертывания, другие параметры меняются при каждом варианте. Для трансформации конфигурационного файла можно воспользоваться XSLT/XPath, передавая входные значения в качестве параметров. Вот пример преобразования:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:sc="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"
  exclude-result-prefixes="sc"
  version="1.0">
 
  <xsl:param name="Connections" select="'7'"/>
  <xsl:param name="Storage" select="'dfltwthstore:::yARsaf523as5uoaarOY539=='"/>
  <xsl:param name="Logs" select="'dfltlogstore:::R2afFEsrT4eeFT8sWadsUf=='"/>
 
 
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
 
  <xsl:template match="sc:Setting[@name = 'Connections']/@value">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="$Connections"/>
    </xsl:attribute>
  </xsl:template>
 
  <xsl:template match="sc:Setting[@name = 'Storage']/@value">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="$Storage"/>
    </xsl:attribute>
  </xsl:template>
 
  <xsl:template match="sc:Setting[@name = 'Logs']/@value">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="$Logs"/>
    </xsl:attribute>
  </xsl:template>
 
</xsl:stylesheet>

В качестве трансформатора можно воспользоваться утилитой msxsl.exe:

msxsl.exe configurationtemplate.cscfg service.xsl -o configuration.cscfg Connections=8

Если в командной строке заданы параметры (в нашем случае Connections=8), то они переопределяют значения параметров, по умолчанию заданных в xsl-листе.

На выходе получим:

<?xml version="1.0" encoding="UTF-16"?><ServiceConfiguration serviceName="YourServiceName" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="Controller">
    <Instances count="5"></Instances>
    <ConfigurationSettings>
      <Setting name="keepalive" value="true"></Setting>
      <Setting name="Storage" value="dfltwthstore:::yARsaf523as5uoaarOY539=="></Setting>
      <Setting name="Logs" value="dfltlogstore:::R2afFEsrT4eeFT8sWadsUf=="></Setting>
    </ConfigurationSettings>
  </Role>
  <Role name="BasicFunctions">
    <Instances count="3"></Instances>
    <ConfigurationSettings>
      <Setting name="Connections" value="8"></Setting>
      <Setting name="Storage" value="dfltwthstore:::yARsaf523as5uoaarOY539=="></Setting>
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

Автоматизация развертывания сервиса

Для решения задачи воспользуемся PowerShell-командлетами, входящими в состав пакета Windows Azure Service Management CmdLets. Перед началом работы нам потребуется создать сертификат и разместить его в облаке (подробности в картинках). После этого нужно подготовить свой скрипт, не забыв задать значения параметров, которые необходимы для его работы. Как и в случае с конфигурационным файлом, меняющиеся параметры нужно передавать из командной строки или зачитывать из конфигурационного файла. Для компактности изложения в примере ниже передаются два параметра (слот и метка), а остальные параметры заданы в теле скрипта.

param([string]$slot, [string]$label)
 
if (!$slot)  { $slot='Staging' }
if (!$label) { $label='NoName' }
 
$cert = Get-Item cert:\CurrentUser\My\0B47A3C9DB926E0D98211C45A1096231EACB57C0
$sub = "9bd4773c-2346-5c34-7a6b-d45b782da12c"
$servicename = 'controller'
$storagename = 'controllerstorage'
$package = "d:\deployment\test\controller\controllerservice.cspkg"
$config = "d:\deployment\test\controller\ServiceConfiguration.cscfg"
 
 
Add-PSSnapin AzureManagementToolsSnapIn
 
Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub |
    Get-Deployment -Slot $slot |
    Set-DeploymentStatus 'Suspended' |
    Get-OperationStatus -WaitToComplete
 
Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | 
    Get-Deployment -Slot $slot | 
    Remove-Deployment | 
    Get-OperationStatus -WaitToComplete
 
 
New-Deployment -serviceName $servicename -storageserviceName $storagename -subscriptionId $sub -certificate $cert -slot $slot -package $package -configuration $config -label $label |
Get-OperationStatus -WaitToComplete
 
 
Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | 
    Get-Deployment -Slot $slot | 
    Set-DeploymentStatus 'Running' | 
    Get-OperationStatus -WaitToComplete

Запуск:

powershell .\service.ps1 -slot 'Production' -label '2010-02-15-b'

Что делает скрипт: останавливает сервис, удаляет его, размещает новую версию и запускает сервис. В составе пакета azurecmdlets есть и другие полезные командлеты. Командлеты снабжены подробным описанием.

Собираем воедино

У нас есть кирпичики. Теперь из них можно построить систему. Вот один из вариантов:

1. создается система каталогов. Каталоги первого уровня: пространства развертывания (к примеру, Live, Test, Dev). В каждом из этих каталогов размещаются подкаталоги сервисов (например, Test\Сontroller, Test\BasicFunctions). В этих подкаталогах размещаются соответствующие пакеты сервисов и файлы с конфигурационными параметрами. Например, ночной билд сервиса Сontroller попадает в Dev\Controller для первичной проверки. Или же пакет из Test\BasicFunctions попадает в Live\BasicFunctions после полноценного тестирования.

2. создается скрипт deploy.cmd, который работает так:

deploy.cmd Test    – обновить все сервисы в пространстве Test
deploy.cmd Test Controller BasicFunctions    – обновить cервисы Controller и BasicFunctions в пространстве Test, а остальные сервисы оставить без изменений.

Скрипт deploy.cmd заходит в соответствующие каталоги и для каждого сервиса считывает конфигурационные параметры, выполняет xsl-преобразование и запуск powershell-скрипта.

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

15.02.2010 Капитан Аляска | Автоматизация | Комментарии

PowerShell: автоматизация тестирования GUI

Добрый день.

Продолжаем разговор о PowerShell. В поставку оболочки входит больше сотни командлетов (cmdlets), облегчающих выполнение административных задач в среде Windows. В то же время, для автоматизации тестирования GUI потребуются дополнительные средства: командлеты, учитывающие специфику тестируемых приложений, либо прямое обращение к классам Microsoft .NET Framework.

В статье “UI Automation with Windows PowerShell” Dr. James McCaffrey объясняет принципы создания и использования командлетов, способных работать с элементами графического интерфейса. По ссылке можно скачать cамораспаковывающийся архив TestRun2007_12.exe, в состав которого входит исходный код командлетов (CustomUICmdletsLib) и тестируемого приложения (TheAppToTest). После сборки в Visual Studio соответственно получаем CustomUICmdletsLib.dll и TheAppToTest.exe. Библиотеку нужно зарегистрировать с помощью прилагаемого Microsoft.PowerShell_profile.ps1:

function RegisterUILib
{
  write-host "registering custom cmdlets for UI automation`n"
  $env:path = $env:path += ";C:\Windows\Microsoft.NET\Framework\v2.0.50727"
  sl 'C:\UIautomationWithPowerShell\CustomUICmdletsLib\bin\Debug'
  installutil.exe CustomUICmdletsLib.dll | out-null
  add-pssnapin LibPSSnapin
  write-host "get-window, get-control, get-controlByIndex, send-chars, send-click"
  write-host "get-listBox, send-menu, and get-textBox custom cmdlets are enabled `n"
}
RegisterUILib # invoke function
set-location C:\UIautomationWithPowerShell

В результате в нашем распоряжении оказываются следующие командлеты: get-window, get-control, get-controlByIndex, send-chars, send-click, get-listBox, send-menu, get-textBox. Скрипт testScenario.ps1, присутствующий в архиве, выполняет запуск тестируемого приложения и операции с ним (нахождение окна, нажатие на кнопки, ввод текста и т.п.). Изучение, модификация и запуск этого скрипта (он довольно простой) позволят понять специфику командлетов.

Вот еще три примера реализации:

1. Windows Automation Snapin for PowerShell. Представлены следующие командлеты: Select-Window, Select-Control, Send-Click, Send-Keys, Set-WindowActive, Set-WindowPosition, Get-WindowPosition, Remove-Window. Вот вступительное слово от автора. Определенный интерес представляет и предыдущая версия этих командлетов, снабженная примером автоматизации работы Notepad (вот краткое описание).

2. PowerShell Scripts for Testing. Примеры использования этой библиотеки можно почерпнуть в блоге ее создателей.

3. PowerShell Community Extensions. Неплохая подборка командлетов и скриптов.

Стоит отметить, что PowerShell можно применять и для тестирования Web-приложений. Вот небольшой пример (получить текст web-страницы и проверить наличие в ней определенной строки):

$url = "http://openquality.ru"
$pattern = "OpenQuality"

$obj = new-object System.Net.WebClient
$page = $obj.DownloadString($url)

if($page -match $pattern) {
    write-output "OK"
} else {
    write-output "Failed"
}

Подходы к тестированию Web-интерфейса изложены в статье “Web UI Automation with Windows PowerShell”, где Dr. James McCaffrey рассматривает примеры работы с элементами web-страницы.

Эффективность применения PowerShell в автоматизации тестирования графического интерфейса напрямую зависит от объекта тестирования. Это .Net-приложение? Есть необходимые командлеты или .Net-классы? Опыт программирования в среде С#? В таких случаях PowerShell достоин самого серьезного рассмотрения.

Хорошим инструментом для работы с PowerShell-скриптами является графическая оболочка PowerGUI, которая позволяет не только запускать готовые скрипты в различных конфигурациях, но и создавать и отлаживать новые.

Всего доброго. Оставайтесь с нами.

05.12.2008 Капитан Аляска | Автоматизация | Комментарии