-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtesting.tex
211 lines (125 loc) · 26.2 KB
/
testing.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
\chapter{Тестирование модулей и манифестов}
Ошибки в манифестах Puppet часто могут привести как к их неработоспособности, так и к нарушению работы систем и потере данных. Поэтому перед запуском новых версий их необходимо сначала проверять. Методика тестирования может сильно отличаться в зависимости от того, в каких условиях и с какими целями проводятся тесты. Рассмотрим, какими средствами можно выполнять проверку модулей и манифестов.
\section{Функциональное тестирование}
Проведение тестов на работающей системе обычно может привести к нарушению её работы и не рекомендуется, иногда может не быть возможности использовать другие методы. В этом случаем можно проводить тестирование на одном из рабочих серверов, или, лучше, на специальной тестовой системе.
Для того, чтобы разработка и отладка новых манифестов не влияла на работу остальных серверов, можно использовать механизм окружений на управляющей системе. Кроме основного набора модулей и манифестов, которые используются всеми серверами, создается еще один дополнительный тестовый набор, который может использоваться только тестовой системой. Изменения в тестовом наборе никак не влияют на работу остальных серверов, но позволяют легко проводить отладку, использую для этого единую инфраструктуру.
Чтобы создать тестовое окружение добавляем в конфигурационный файл \textbf{puppet.conf} на управляющем сервере следующие строчки:
\begin{verbatim}
[testing]
modulepath = $confdir/environments/testing/modules
manifest = $confdir/environments/testing/manifests/site.pp
\end{verbatim}
Мы указали, что для окружения \texttt{testing} модули и манфесты будут находиться в отдельном каталоге \texttt{environments/testing}, который находится рядом с основным набором модулей.
На тестовой системе теперь можно запустить агент с дополнительным параметром \texttt{-{}-environment testing}, чтобы он получил каталог, собранный из тестовой ветки.
Кроме \texttt{testing} модно создать много дополнительных окружений, например разделив разработку и тестирование, или эту же технологию можно использовать для разделения между серверами разных подразделений компании. Окружение по умолчанию называется \texttt{production}, и оно используется, если не создано никаких дополнительных окружений.
В процессе разработки изменения вносятся в тестовую ветку и на одной из систем, которая используется как тестовая, можно проверить их результат. Самый простой способ --- сначала запустить Puppet в режиме \textbf{noop}, с котором никакие изменения не будут на самом деле произведены, а только будет показано, что агент бы сделал. Запустить агент в таком режиме можно так:
\begin{verbatim}
puppet agent --environment=testing --test --noop
\end{verbatim}
Будет выведен список всех изменений, которые были бы сделаны, если бы агент был запущен без ключа \texttt{-{}-noop}. На этом этапе уже можно заметить ошибку, если в списке есть не те изменения, которые хотел выполнить разработчик. Этот метод обычно позволяет обнаружить только логические и смысловые ошибки. Пока нельзя сказать будут ли правильно выполнены все эти изменения и в правильном ли порядке.
Если список изменений выглядит правильным, можно убрать параметр \texttt{-{}-noop} и применить все изменения. При запуске только с параметром \texttt{-{}-test} будут выводиться все выполняемые изменения и ошибки, если они происходят. Такая проверка иногда называется \textit{Smoke Test}, потому что она позволяет быстро проверить не сломали ли систему последние изменения в модуле или манифесте.
\begin{verbatim}
puppet agent --environment=testing --test
\end{verbatim}
Если тест новой версии прошёл успешно на всех тестовых системах, или после исправления всех ошибок и проблем, то можно выложить новую версию из тестового окружения в основное, чтобы оно было применено на всех серверах. Если изменения всё же потенциально могут привести к проблемам, то часто используют поэтапный переход, когда сначала изменения применяются на одной группе серверов, потом, если не возникло проблем, на следующей, и так пока все сервера не будут обновлены.
Использование системы контроля версий позволяет легко вносить изменения, например, сначала в ветку для разработчиков, потом передавать их на тестирование в тестовую ветку, затем, если тесты прошли успешно, передать изменения в основную ветку. Кроме этого можно легко отменить последние изменения и вернуться к более ранней версии, которая работает правильно, если появились непредвиденные проблемы.
Такая методика тестирования уместна, когда Puppet используется для поддержки большой инфраструктуры реальных серверов, которая слишком сложна, чтобы можно было сделать небольшую тестовую модель, которая вела бы себя достаточно похоже на реальную систему.
Тестирование на реальной системе позволяет определить работоспособность манифестов именно в тех условиях, в которых они будут использоваться, или для нескольких ситуаций, которые присутствуют в поддерживаемой системе. Если модуль более универсальный, то можно легко не обнаружить ошибки, которые проявляются в других ситуациях или при редком сочетании параметров.
\section{Модульные тесты}
При разработке отдельного модуля часта приходится проверять его работы в разных окружениях с разными входными данными. Использование реальной инфраструктуры обычно позволяет проверить работу только в некоторых ситуациях.
Если не требуется проверка всего набора модулей и манифестов сразу, то можно использовать модульные тесты, которые позволяют проверить работоспособность каждого модуля отдельно, используя при этом специальные тестовые окружения, позволяющие быстро смоделировать разные состояния системы.
Для использование таких тестов сначала нужно подготовить примеры использования модуля в разных режимах. Для этого в корне модуля создадим каталог \textbf{tests}. В него можно положить несколько файлов-манифестов, которые включают тестируемый модуль. Эти файлы выполняют две функции. Во-первых, они очень полезны как пример использования этого модуля в разных режимах. Другие разработчики могут брать секции из этих тестов и создавать на их основе свои манифесты. Во-вторых, эти манифесты могут быть напрямую применены при помощи Puppet агента, работающего в локальном режиме, для проверки работы модуля в разных окружениях.
Рассмотрим примеры тестирования нескольких Puppet модулей.
\subsection{Тестирование обычного класса}
Начнём с простого модуля, содержащего только один обычный класс. Этот модуль предназначен для установки и настройки NTP сервера на операционных системах семейства Debian и RedHat. Сначала производится установка пакета, потом скачивается конфигурационный файл и запускается сам ntp демон. Конфигурационные файлы отличаются для разных операционных систем. Правильный файл должен автоматически выбираться из набора заранее приготовленных файлов.
\lstinputlisting[title={Модуль для установки и настройки NTP}]{code/ntp/manifests/init.pp}
Для того, чтобы протестировать этот модуль создадим каталог \textbf{tests}, и положим в него маленький манифест, который включает этот модуль.
\VerbatimInput[fontsize=\normalsize,frame=none]{code/ntp/log/tree.log}
\lstinputlisting[title={Тест включения модуля ntp}]{code/ntp/tests/ntp.pp}
Теперь попробуем применить этот манифест. Сначала запустим его в режиме без настоящих изменений.
\begin{verbatim}
puppet apply --verbose --noop --modulepath="." "ntp/tests/ntp.pp"
\end{verbatim}
\VerbatimInput{code/ntp/log/noop.log}
Был показан список изменений, которые могли бы быть выполнены при настоящем проходе. Теперь выполним эту команду без ключа \textbf{--noop}.
\VerbatimInput{code/ntp/log/test.log}
Пакет был успешно установлен и демон запущен.
\subsection{Тестирование параметрического класса}
Теперь создадим несложный модуль, содержащий параметрический класс. Для примера попробуем устанавливать и управлять демоном \textbf{acpid}. Модуль должен уметь включать и выключать сервис, например если он не нужен на виртуальной системе.
\lstinputlisting[title={Модуль для установки и управления acpid}]{code/acpid/manifests/init.pp}
Чтобы протестировать работу этого модуля нужно запустить его на разных операционных системах как в режиме включения, так и выключения сервиса. Создадим в корне модуля папку \textbf{tests}, а в ней создадим два файла, использующих модуль acpid в режиме включения и выключения.
\VerbatimInput[fontsize=\normalsize,frame=none]{code/acpid/log/tree.log}
\lstinputlisting[title={Тест включения acpid}]{code/acpid/tests/acpid_on.pp}
\lstinputlisting[title={Тест выключения acpid}]{code/acpid/tests/acpid_off.pp}
Теперь попробуем запустить эти тесты.
\begin{verbatim}
puppet apply --verbose --modulepath="." "acpid/tests/acpid_on.pp"
puppet apply --verbose --modulepath="." "acpid/tests/acpid_off.pp"
\end{verbatim}
\VerbatimInput{code/acpid/log/test_on.log}
\VerbatimInput{code/acpid/log/test_off.log}
Первый тест установил пакет \textbf{acpid} и включил сервис, а второй - выключил сервис.
\subsection{Тестирование определения}
В последнем примере мы создадим определение, или определяемый ресурс. В отличие от классов и параметрических классов может быть включено несколько экземпляров определений. Предположим, что нам нужно создавать пользователей, автоматически создавая в их домашнем каталоге конфигурационный файл для vim.
\lstinputlisting[title={Создание пользователя вместе с конфигурационным файлом}]{code/vimuser/manifests/init.pp}
Добавим два тестовых манифеста, которые создают и удаляют пользователей.
\VerbatimInput[fontsize=\normalsize,frame=none]{code/vimuser/log/tree.log}
\lstinputlisting[title={Создание пользователей}]{code/vimuser/tests/vimuser_add.pp}
\lstinputlisting[title={Удаление пользователей}]{code/vimuser/tests/vimuser_remove.pp}
Сначала запустим тест создания пользователей с ключём \textbf{noop}.
\begin{verbatim}
puppet apply --verbose --noop --modulepath="." "vimusers/tests/vimuser_add.pp"
\end{verbatim}
\VerbatimInput{code/vimuser/log/noop.log}
Здесь мы видим, что попытка проверить возможность создания файлов привела к ошибке. Это произошло потому, что в тестовом запуске пользователи на самом деле не были созданы, и файлы создать не получилось, поскольку таких пользователей не существует. При нормальном запуске пользователи были бы созданы, и файлы тоже были бы нормально обработаны. Этот пример показывает, что иногда Puppet агент в режиме \textbf{noop} может показывать неверный результат, и не нужно полностью доверять его результатам без проверки.
Теперь запустим этот манифест в нормальном режиме, и убедимся в том, что он отработал нормально.
\begin{verbatim}
puppet apply --verbose --modulepath="." "vimuser/tests/vimuser_add.pp"
\end{verbatim}
\VerbatimInput{code/vimuser/log/add.log}
Теперь запустим второй манифест и проверим удаление пользователей.
\VerbatimInput{code/vimuser/log/remove.log}
\subsection{Автоматизация модульного тестирования}
При большом количестве используемых модулей становится очень сложно вручную тестировать каждый из них, особенно если требуется тестирование в разных окружениях. Рассмотрим как можно автоматизировать такие тесты и сделать их выполнение более быстрым.
Для создание тестовых окружений удобно использовать специальную программу Vagrant (\url{http://vagrantup.com}). Он представляет собой небольшой скрипт, который может быстро создавать, запускать и удалять тестовые системы на VirtualBox и часто используется разработчиками, чтобы можно было быстро создать окружение для запуска их проектов.
\subsubsection{Подготовка системы к запуску тестов}
\begin{description}
\item[Vagrant] Первым делом необходимо скачать и установить сам Vagrant. Либо скачиваем и устанавливаем последнюю версию отсюда \url{http://downloads.vagrantup.com/}, либо используем пакетный менеджер.
\item[VirtualBox] Теперь нужно скачать и установить VirtualBox. Дистрибутив можно скачать здесь \url{https://www.virtualbox.org/wiki/Downloads}. Лучше использовать именно версию от Oracle, а не Community версию.
\item[VirtualBox Extensions] Расширения VirtualBox, которые не поддерживаются Community версией. Позволяют использовать загрузку по сети виртуальных машин и проброс USB устройств в гостевые системы. Они не требуются для использования Vаgrant и тестирования Puppet модулей, но могут быть очень полезны для других задач.
\end{description}
\subsubsection{Использование Vagrant}
Vagrant создаёт виртуальные системы из упакованных файлов-образов. Для того, чтобы создать образ в корневом каталоге проекта нужно создать специальный конфигурационный файл \textbf{Vagrantfile}. При создании начального конфигурационного файла можно сразу указать, откуда скачать файл-образ, и как он будет называться после установки. Например создадим тестовую систему на Ubuntu 12.04 x32:
\begin{verbatim}
vagrant init precise32 http://files.vagrantup.com/precise32.box
\end{verbatim}
Теперь можно попробовать запустить систему при помощи команды:
\begin{verbatim}
vagrant up
\end{verbatim}
При этом будет скачан образ, импортирован в новую виртуальную машину и она будет включена и загрузится. После этого можно зайти на неё при помощи команды:
\begin{verbatim}
vagrant ssh
\end{verbatim}
Содержимое того каталога, из которого был запущен Vagrant, будет доступно как \texttt{/vagrant} внутри виртуальной машины. Можно начинать тестировать ваш проект прямо в этом каталоге. Если необходимо подключить данные в другое место или использовать проброс портов в виртуальную систему, можно отредактировать Vagrantfile и раскомментировать соответствующие строчки.
Если проект требует более сложного окружения, то можно использовать Puppet, Chef, или другой способ автоматической настройки, для подготовки виртуальной машины. Для этого укажите в Vagrantfile путь к вашим скриптам или манифестам. Для больших проектов, требующих несколько виртуальных машин предусмотрен режим нескольких окружений. Подробнее об использовании Vagrant можно прочитать здесь \url{http://docs.vagrantup.com/v2/getting-started/index.html}, но для начала работы будут нужны только следующие команды:
\begin{description}
\item[vagrant up] Создание или включение виртуальной машины.
\item[vagrant halt] Выключение виртуальной машины.
\item[vagrant suspend] Сохранение состояния виртуальной машины и её выключение.
\item[vagrant ssh] Вход на виртуальную машину
\item[vagrant -h, vagrant (command) -h] Справка по всем или по одной команде.
\item[vagrant box *] Команды для добавления, просмотра и удаления сохранённых образов.
\item[vagrant package] Упаковка текущей системы в новый файл-образ, который можно снова использовать.
\end{description}
Лёгкое создание своих файлов-образов и возможность их распространения позволяют создать большое количество различных окружений, подходящих для тестирования Puppet и любых других проектов.
\subsection{Запуск тестов}
Теперь подготовим скрипт, который сможет автоматически запускать тесты всех Puppet модулей и сообщать о результатах тестирования. Сначала создадим несложный Vagrantfile, который позволит создать виртуальную систему Centos6 x64:
\VerbatimInput{code/Vagrantfile}
Теперь напишем скрипт, который автоматически запускает в виртуальном окружении команды Puppet, выполняя по очереди все модульные тесты.
\lstinputlisting[title={Скрипт для автоматического тестирования модулей},language=Bash]{code/vagrant_test.sh}
Запустим этот скрипт чтобы выполнить все рассмотренные выше модульные тесты и вывести общий результат по всем тестам.
\VerbatimInput{code/vagrant_test.log}
После завершения тестирования виртуальная системы будет возвращена в исходное состояние при помощи snapshot. Если при тестировании были обнаружены неполадки, то теперь можно их исправить и повторить тесты. Системы автоматического тестирование могут использовать подобные скрипты для регулярной проверки всех используемых Puppet модулей и сбора статистики по успешных проходам и найденным ошибкам.
Если требуется тестирование в нескольких условиях, например в разных операционных системах, то можно повторять тесты с разными файлами-образами, подменяя их имя в Vagrantfile, или передавая имя файла и путь к нему через переменные окружения, например вот так:
\lstinputlisting[title={Передача переменных среды в Vagrantfile}]{code/Vagrantfile.env}