Molecule, Serverspec による Ansible Role の開発環境構築


はじめに

Molecule3系を使って、 Ansible Role を開発する環境を構築する手順について模索したので、結果を記録として残します。
なお、Molecule3系では Serverspec をサポートしなくなりましたが、手に馴染んでいるので、どうやったら使えるようになるのかも検討しました。

前提

  • MacOS
  • Python3系がインストールされている

必要なパッケージ等のインストール

Molecule は pip から、Serverspec は gem からインストールします。

Molecule

pip3 install molecule
pip3 install docker
pip3 install 'molecule[docker]'

Serverspec

Serverspec, Serverspec-runner をインストールします。
Serverspec-runner は、Serverspec の wrapper で、テスト結果をCSVや表形式で出力してくれるので、テスト完了後のまとめに便利なので、好んで使っています。

gem install serverspec
gem install serverspec-runner
gem install docker-api

Role の雛形の作成

Ansible Role 雛形の作成

molecule init を使います。

ROLE={{ ROLE名 }}
molecule init role ${ROLE}
cd ${ROLE}
vi molecule/default/molecule.yml
molecule/default/molecule.yml
---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: instance
    image: docker.io/centos:8
    pre_build_image: true
    privileged: True
    command: /sbin/init
provisioner:
  name: ansible
verifier:
  name: ansible

Serverspec 雛形の作成

serverspec-runner -r を使います。

serverspec-runner -r .
vi spec/spec_helper.rb
--- spec_helper.rb.default  2020-08-27 08:14:59.000000000 +0900
+++ spec_helper.rb  2020-08-27 08:14:51.000000000 +0900
@@ -63,8 +63,9 @@
     set :ssh_options, options
     set :backend, :ssh
     set :request_pty, true
-  #else
-  #  set :backend, :exec
+  else
+     set :backend, :docker
+     set :docker_container, 'instance'
   end

   prev_desc_hierarchy = nil

host がデフォルトの 127.0.0.1 のときは instance という名前の Docker コンテナを対象にするようにしました。

開発の例

Roleのサンプル

httpdをインストールするタスクとテストを書いてみます。

tasks/main.yml
---
- name: install httpd package
  yum:
    name: httpd
    state: latest

- name: start httpd
  systemd:
    name: httpd
    state: started
    enabled: yes
molecule/default/verify.yml
---
- name: Verify
  hosts: all
  tasks:
  - ignore_errors: yes
    block:
    - name: httpd package
      shell: yum list installed | grep -e '^httpd\.'
      register: result_rpm

    - name: httpd proccess
      shell: ps -ef | grep http[d]
      register: result_proc

    - name: httpd service
      shell: systemctl is-enabled httpd
      register: result_enabled

  - name: result
    assert:
      that: "{{ result.failed == false }}"
    loop:
      - "{{ result_rpm }}"
      - "{{ result_proc }}"
      - "{{ result_enabled }}"
    loop_control:
      loop_var: result

Molecule の実行

# Dockerコンテナの作成、Roleの実行、テスト、コンテナの破棄まで全て行う
molecule test

# テストまで行う(コンテナは破棄しない)
molecule converge

# Dockerコンテナの破棄
molecule destroy

Serverspecのサンプル

spec/httpd/sample_spec.rb
require 'spec_helper'

describe package('httpd'), :if => os[:family] == 'redhat' do
  it { should be_installed }
end
describe service('httpd'), :if => os[:family] == 'redhat' do
  it { should be_enabled }
  it { should be_running }
end
describe port(80) do
  it { should be_listening }
end
scenario.yml
httpd:
  - anyhost-01
---
anyhost-01:
  host:        127.0.0.1

Serverspecの実行

serverspec-runner

driver に vagrant を使う

上記の手順で molecule test を実行すると、以下のような firewalld のタスクでエラーになってしまいました。

tasks/main.yml
- name: "open firewalld ntp port"
  firewalld:
    zone: public
    service: ntp
    permanent: yes
    state: enabled
    immediate: yes

driver に docker ではなく、 vagrant を指定するとエラーは解消されたので、手順を以下に示します。

Molecule

molecule-vagrant をインストールします。

pip3 install molecule-vagrant

molecule.yml は以下のように編集します。

molecule/default/molecule.yml
dependency:
  name: galaxy
driver:
  name: vagrant
  provider:
    name: virtualbox
platforms:
  - name: instance
    box: bento/centos-8
    interfaces:
      - network_name: private_network
        ip: 192.168.33.11
provisioner:
  name: ansible
verifier:
  name: ansible

なお、 molecule init を実行するときに --driver-name vagrant を指定すると driver の指定ができます。

molecule init role ${ROLE} --driver-name vagrant

Serverspec

driver を vagrant にした場合は、 scenario.yml を以下のようにします。

scenario.yml
example:
  - anyhost-01
---
anyhost-01:
  host: 192.168.33.11
  ssh_opts:
    user: vagrant
    password: vagrant

参考