腐女子エンジニアの日記

創作と技術と時々音楽

GitLabとMoleculeでPlaybookのテストをしてみる

あっという間に2月になってました。 今回はGitLabとMoleculeを使用してPlaybookのCIを回してみようと言うお話です。

ゴール

  • ローカル環境に同様の環境を用意し、GitLab CI上で行なっているものと同様のテストを実行できるようにする。
  • GitLab CIを使用してPlaybookのテストの自動実行を実現する。

ローカル環境前提

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

GitLab CI/Moleculeざっくり概要

GitLab CI

  • GitLab CI/CDとはGitLabに備わっているCI/CDのためのツールです。
  • git push等のイベントを受け、ジョブを自動実行してくれます。
  • GitLab CIのドキュメント: https://docs.gitlab.com/ee/ci/

Molecule

  • AnsibleのRoleテスト用ツールです。
  • lint、一時的な環境構築、Playbook実行、ユニットテスト実行、環境削除までの一連の流れをサポートしています。
  • 今回はPlaybookのテストを行いたいと思います。多分ちょっと例外的な使い方だと思います。

ドキュメント molecule.readthedocs.io

これから作成するもの

  1. Molecule実行用ディレクトリ(molecule/)
  2. GitLab CI実行用ファイル(.gitlab-ci.yml)
  3. Molecule実行用イメージ(Dockerfile)

手順

ゴールはこんな感じです。 f:id:dcn_f:20200210135303p:plain

最初にローカル環境を整えます。

Moleculeインストール

  1. pipを使用してmoleculeをインストールします。Moleculeで使用する環境がdockerの場合、併せてdockerをインストールします。
$ pip3 install molecule
$ pip3 install docker

1. Molecule実行用ディレクトリ(molecule/)作成

初期化

  • molecule initコマンドを使用してmoleculeで使用するファイル群を作っていきます。
  • 今回はroleのテストは行いませんので、molecule init scenarioを使用します。
# まずはシナリオ名を指定せずにdefaultディレクトリを作成
# defaultディレクトリがないと実行できません
$ molecule init scenario 
# 今回利用するシナリオを作成(`createuser`と言う名前にします)
$ molecule init scenario -s createuser
  • 作成されるディレクトリ構成はこんな感じです。
  • 以降、createuser/以下のファイルのみを修正していきます。
molecule
├── createuser
│   ├── Dockerfile.j2
│   ├── INSTALL.rst
│   ├── molecule.yml
│   └── tests
│       ├── __pycache__
│       │   ├── test_createuser.cpython-37-pytest-5.3.5.pyc
│       │   └── test_default.cpython-37.pyc
│       └── test_createuser.py
└── default
    ├── Dockerfile.j2
    ├── INSTALL.rst
    ├── molecule.yml
    └── tests
        ├── __pycache__
        │   └── test_default.cpython-37.pyc
        └── test_default.py

molecule.yml

  • molecule.ymlはmolecule実行時の設定を記述するファイルです。
  • lintツールやテストツールの指定等ができます。
  • シナリオ作成時に作成されるファイルは下記のようになっています。
---
dependency:
  name: galaxy
driver:
  name: docker
lint:
  name: yamllint
platforms:
  - name: instance
    image: centos:7
provisioner:
  name: ansible
  lint:
    name: ansible-lint
verifier:
  name: testinfra
  lint:
    name: flake8
  • 今回はPlaybookを下記のように修正して使用します。
---
dependency:
  name: galaxy
driver:
  name: docker
lint:
  name: yamllint
# インスタンス名を変更
platforms:
  - name: createuser
    image: centos:7
# 実行するPlaybookを指定
provisioner:
  name: ansible
  lint:
    name: ansible-lint
  playbooks:
    converge: ../../createuser.yml 
verifier:
  name: testinfra
  lint:
    name: flake8
# シナリオ名を指定
scenario:
  name: createuser

テストファイル(testinfra)

  • 今回はtestinfraというテストツールを使用します。
  • 接続先に対してコマンドを実行し、あるべき状態かを確認することができます。
  • また、Ansibleのhostsやモジュールをサポートしており、Playbookのテストに適していると思います。

testinfra.readthedocs.io

  • 初期化時は下記のような状態となっています。
import os

import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    os.environ['MOLECULE_INVENTORY_FILE']
).get_hosts('all')


def test_hosts_file(host):
    f = host.file('/etc/hosts')

    assert f.exists
    assert f.user == 'root'
    assert f.group == 'root'
  • ユーザが作成されたことを確かめるよう記述します。
  • 色々かけるので、詳細はドキュメントサイトを確認ください。
import os

import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    os.environ['MOLECULE_INVENTORY_FILE']
).get_hosts('all')


def test_hosts_file(host):
    f = host.file('/etc/hosts')

    assert f.exists
    assert f.user == 'root'
    assert f.group == 'root'


def test_user(host):
    user = host.user('testuser')

    assert user.name == 'testuser'

ローカル環境で実行してみる

  • ここで一回ローカル環境で実行してみましょう。
  • convergeで詰まった場合はdockerのインストール周りを疑ってみてください。
$ cd (moleculeディレクトリがある階層)

# lint
$ molecule lint -s createuser

# syntax check
$ molecule syntax -s createuser

# 環境構築まで
$ molecule converge -s createuser

# unit test
$ molecule verify -s createuser

# 環境削除
$ molecule destroy -s createuser

2. GitLab CI実行用ファイル(.gitlab-ci.yml)作成

  • CI設定は.gitlab-ci.ymlというファイルを用いて記述します。
  • 1から書き上げましょう!
---
image: registry.gitlab.com/kitiful1812/molecule-ci/molecule:latest

services:
  - docker:dind

stages: 
  - test

test-createuser:
  stage: test
  tags: 
    - docker
  script: 
    - molecule lint -s createuser
    - molecule syntax -s createuser
    - molecule converge -s createuser
    - molecule verify -s createuser
    - molecule destroy -s createuser

3. Molecule実行用イメージ(Dockerfile)作成

  • 上でかいた通り、GitLab CIでジョブを実行するためにMoleculeのイメージを作成しておきます。
  • ドキュメントサイトには.gitlab-ci.yml内に直接記述するようかいてありますが いちいち書くのが面倒なので、Dockerfileを作成しておきます。
FROM docker:git

RUN apk update && apk add --no-cache docker \
    python3-dev py3-pip docker gcc git curl build-base \
    autoconf automake py3-cryptography linux-headers \
    musl-dev libffi-dev openssl-dev openssh 
RUN pip3 install ansible molecule docker
$ docker build -t (イメージ名)
$ docker push 
  • これでいつでも同じイメージを起動することができます。便利!

まとめ

  • これでGitLab CI/ローカル環境で同様なテストを実現することができました!
  • 是非実践してみてください。

備考