Мой коллега написал прекрасный блог о локальном тестировании ролей Ansible с использованием KitchenCI. Очень быстрый и простой инструмент, состоящий из ruby gem'ов, доступный на каждой ОС, который также работает с разными инструментами тестирования (например Serverspec и Pester). Коллега разрабатывал это решение под нужды своих проектов (provision и deploy исключительно под Windows), что на первый взгляд стало проблемой, потому что:
- Я тоже люблю Ansible
- Ansible мне нужен, чтобы управлять Linux
- Я не хочу создавать еще один репозиторий на GitHub для отдельного тестирования Linux-ролей, потому что не хочу плодить сущности (Бритва Оккама наше все)
Кому интересно, что было дальше, прошу под кат.
После небольшой дискуссии мы договорились, что я адаптирую его инструмент под оба окружения, а конечный пользователь инструмента (будь то инженер или разработчик), сможет пользоваться всеми его компонентами или только частью. Но для начала — краткое описание, что работает сейчас.
А сейчас у нас имеется стандартная роль Ansible, в отдельной директории лежит kitchen, в котором расположены тесты Pester для тестирования конфигурации WinServer'а и настройки, собственно, самого kitchen. в файле .kitchen имеется 2 конфигурации для Vagrant box'ов (Ansible + Winserver), сценарии развертывания и пути до тестов. Кому интересно, исходники тут.
По 4 командам в директории kitchen, пройдет наше тестирование от начала и до конца.
- kitchen create — создаст нашу локальную виртуальную инфраструктуру
- kitchen converge — применит роли ansible
- kitchen verifiy — применит тест suite из verifier'а
- kitchen destroy — уберет за собой.
Первый раз будет выполняться невероятно долго (Windows box штука очень тяжелая), поэтому надо запастись терпением.
Важный момент, которые я забыл упомянуть: эта конфигурация — скелет роли, которую разработчик может изучить, чтобы понять как ему разрабатывать и тестировать свою роль. Я не представляю себе кейс, когда разработчик разрабатывает одну роль, которая должна работать на обеих экосистемах.
Но тем не менее, корпоративный GitHub не резиновый, поэтому надо немного экономить.
Начнем с того, что мы настроим роль playbook'а, чтобы она была универсальна для обеих ОС. Здесь нам помогут банальные факты Ansible.
---
# This play installs IIS, if you run it on windows box
- name: install web-server feature
win_feature:
name: Web-Server
state: present
when: ansible_os_family == "Windows"
- name: deploy iis start page template
template:
src: iisstart.j2
dest: C:inetpubwwwrootiisstart.htm
when: ansible_os_family == "Windows"
# This play installs Nginx, if you run it on linux box
- name: install nginx
yum: name=nginx state=latest
when: ansible_os_family == "RedHat"
- name: start nginx
service: name=nginx state=started enabled=True
when: ansible_os_family == "RedHat"
Как видно, в первом случае мы устанавливаем в Windows роль IIS, во втором — устанавливаем и запускаем Nginx.
Теперь к тестам. Создаем новую директорию в kitchen/tests/integration/default (default — это название нашего тест suit'a) под названием serverspec. В нем у нас будет всего один файл defailt_spec.rb
Я не очень силен в ruby, поэтому сделал грязно без spec-helper'а
require 'rubygems'
require 'bundler/setup'
require 'serverspec'
require 'pathname'
require 'net/ssh'
RSpec.configure do |config|
set :host, ENV['KITCHEN_HOSTNAME']
# ssh options at http://net-ssh.github.io/net-ssh/Net/SSH.html#method-c-start
# ssh via ssh key (only)
set :ssh_options,
:user => ENV['KITCHEN_USERNAME'],
:port => ENV['KITCHEN_PORT'],
:auth_methods => [ 'publickey' ],
:keys => [ ENV['KITCHEN_SSH_KEY'] ],
:keys_only => true,
:paranoid => false,
:verbose => :error
set :backend, :ssh
set :request_pty, true
end
describe package('nginx'), :if => os[:family] == 'redhat' do
it { should be_installed }
end
describe service('nginx'), :if => os[:family] == 'redhat' do
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
end
Здесь у нас всего три проверки: пакет установлен, служба запущена и на автостарте, и на порту 80 кто-то слушает.
Небольшой совет тем, кто, как и я, не умеет в Ruby — согласно документации serverspec-init сгенерирует вам дефолтный тест, как в примере выше.
Итак, роль — есть, тесты — есть. Теперь надо настроить саму кухню. Коллега вынужден поднимать две машины, поскольку развернуть маленький ansible сервер гораздо проще, чем установить его на Windows. В моем же случае устанавливать ansible роль будет сам kitchen, поэтому мне хватит одной машинки. Мой скрипт kitchen будет поменьше.
---
driver:
name: vagrant
gui: true
linked_clone: true
platforms:
- name: centos_box
driver_plugin: vagrant
driver_config:
box: centos/7
network:
- [ 'private_network', { ip: '172.28.128.13' } ]
transport:
max_ssh_sessions: 1
provisioner:
name: ansible_playbook
roles_path: ../
role_name: kitchen_test_role
ansible_inventory: inventory/hosts
require_windows_support: true
require_chef_for_busser: false
ansible_host_key_checking: false
ansible_verbose: true
ansible_verbosity: 4
playbook: default_linux.yml
verifier:
name: serverspec
remote_exec: false
suites:
- name: default
verifier:
patterns:
- tests/integration/default/serverspec/default_spec.rb
У меня отдельный ansible_playbook, поскольку в нем роль выполняется только для linux машины в инвентарном файле.
С разработкой в общем-то и покончено. А объяснить kitchen'у какой конфигурацией пользовать довольно легко. Нужно перед выполнением команды kitchen передать ей переменную окружения KITCHEN_YAML=«имя_нашей_конфигурации».
Например:
KITCHEN_YAML=".kitchen_linux.yml" kitchen create/converge/verify/destroy.
Благодарю за внимание.
Автор: v_sadist