KitchenCI + Ansible для Windows и Linux

в 9:35, , рубрики: Ansible, devops, kitchenci

Мой коллега написал прекрасный блог о локальном тестировании ролей 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

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js