著者は、 Write for DOnations プログラムの一環として、 MozillaFoundationを選択して寄付を受け取りました。

序章

Ansible での単体テストは、役割が意図したとおりに機能することを確認するための鍵です。 Molecular は、さまざまな環境に対して役割をテストするシナリオを指定できるようにすることで、このプロセスを容易にします。 Moleculeは、内部でAnsibleを使用して、構成された環境に役割をデプロイするプロビジョナーに役割をオフロードし、ベリファイア( Testinfra など)を呼び出して構成のドリフトをチェックします。 これにより、あなたの役割がその特定のシナリオで環境に予想されるすべての変更を加えたことを確認できます。

このガイドでは、 Apache をホストにデプロイし、CentOS7でFirewalldを構成するAnsibleロールを構築します。 この役割が意図したとおりに機能することをテストするには、 Docker をドライバーとして使用し、サーバーの状態をテストするためのPythonライブラリであるTestinfraを使用してMoleculeでテストを作成します。 MoleculeはDockerコンテナーをプロビジョニングして役割をテストし、Testinfraはサーバーが意図したとおりに構成されていることを確認します。 終了すると、環境間でビルドするための複数のテストケースを作成し、Moleculeを使用してこれらのテストを実行できるようになります。

前提条件

このガイドを開始する前に、次のものが必要です。

  • 1つのUbuntu16.04サーバー。 Ubuntu 16.04を使用したサーバーの初期設定ガイドの手順に従って、root以外のsudoユーザーを作成し、パスワードなしでサーバーに接続できることを確認します。
  • サーバーにDockerがインストールされています。 Ubuntu 16.04 にDockerをインストールして使用する方法の手順1と2に従い、root以外のユーザーをdockerグループに追加してください。
  • Ansibleプレイブックに精通していること。 レビューについては、 Configuration Management 101:Writing AnsiblePlaybooksを参照してください。

ステップ1—環境の準備

ロールとテストを作成するために、最初に仮想環境を作成してMoleculeをインストールしましょう。 Moleculeをインストールすると、Ansibleもインストールされ、プレイブックを使用して役割を作成し、テストを実行できるようになります。

root以外のユーザーとしてログインし、リポジトリが最新であることを確認することから始めます。

  1. sudo apt-get update

これにより、パッケージリポジトリにpython-pipパッケージの最新バージョンが含まれ、pipとPython2.7がインストールされます。 pipを使用して仮想環境を作成し、追加のパッケージをインストールします。 pipをインストールするには、次のコマンドを実行します。

  1. sudo apt-get install -y python-pip

pipを使用して、virtualenvPythonモジュールをインストールします。

  1. python -m pip install virtualenv

次に、仮想環境を作成してアクティブ化します。

  1. python -m virtualenv my_env

これをアクティブにして、アクションがその環境に制限されていることを確認します。

  1. source my_env/bin/activate

pipを使用してmoleculeおよびdockerをインストールします。

  1. python -m pip install molecule docker

これらの各パッケージの機能は次のとおりです。

  • molecule:これは、役割のテストに使用するメインのMoleculeパッケージです。 moleculeをインストールすると、Ansibleが他の依存関係とともに自動的にインストールされ、Ansibleプレイブックを使用して役割とテストを実行できるようになります。
  • docker:このPythonライブラリは、MoleculeがDockerとのインターフェイスに使用します。 Dockerをドライバーとして使用しているため、これが必要になります。

次に、Moleculeでロールを作成しましょう。

ステップ2—分子での役割の作成

環境を設定したら、Moleculeを使用して、Apacheのインストールをテストするための基本的な役割を作成できます。 この役割は、ディレクトリ構造といくつかの初期テストを作成し、Dockerをドライバーとして指定して、MoleculeがDockerを使用してテストを実行するようにします。

ansible-apacheという新しい役割を作成します。

  1. molecule init role -r ansible-apache -d docker

-rフラグは役割の名前を指定し、-dはドライバーを指定します。ドライバーはテストで使用するMoleculeのホストをプロビジョニングします。

新しく作成されたロールのディレクトリに移動します。

  1. cd ansible-apache

デフォルトの役割をテストして、Moleculeが正しく設定されているかどうかを確認します。

  1. molecule test

デフォルトの各テストアクションを一覧表示する出力が表示されます。

Output
--> Validating schema /home/sammy/ansible-apache/molecule/default/molecule.yml. Validation completed successfully. --> Test matrix └── default ├── lint ├── destroy ├── dependency ├── syntax ├── create ├── prepare ├── converge ├── idempotence ├── side_effect ├── verify └── destroy ...

テストを開始する前に、Moleculeは構成ファイルmolecule.ymlを検証して、すべてが正常であることを確認します。 また、テストアクションの順序を指定するこのテストマトリックスも出力します。

役割を作成してテストをカスタマイズしたら、各テストアクションについて詳しく説明します。 今のところ、各テストのPLAY_RECAPに注意し、デフォルトのアクションのいずれもfailedステータスを返さないことを確認してください。 たとえば、デフォルトの'create'アクションのPLAY_RECAPは、次のようになります。

Output
... PLAY RECAP ********************************************************************* localhost : ok=5 changed=4 unreachable=0 failed=0

次に、ApacheとFirewalldを構成するための役割の変更に移りましょう。

ステップ3—ApacheとFirewalldの設定

ApacheとFirewalldを構成するには、ロールのタスクファイルを作成し、インストールするパッケージと有効にするサービスを指定します。 これらの詳細は、デフォルトのApacheインデックスページを置き換えるために使用する変数ファイルとテンプレートから抽出されます。

nanoまたはお気に入りのテキストエディタを使用して、ロールのタスクファイルを作成します。

  1. nano tasks/main.yml

ファイルがすでに存在していることがわかります。 そこにあるものを削除し、次のコードを貼り付けて、必要なパッケージをインストールし、正しいサービス、HTMLのデフォルト、およびファイアウォール設定を有効にします。

〜/ ansible-apache / tasks / main.yml
---
- name: "Ensure required packages are present"
  yum:
    name: "{{ pkg_list }}"
    state: present

- name: "Ensure latest index.html is present"
  template:
    src: index.html.j2
    dest: /var/www/html/index.html

- name: "Ensure httpd service is started and enabled"
  service:
    name: "{{ item }}"
    state: started
    enabled: true
  with_items: "{{ svc_list }}"

- name: "Whitelist http in firewalld"
  firewalld:
    service: http
    state: enabled
    permanent: true
    immediate: true

このプレイブックには、次の4つのタスクが含まれています。

  • "Ensure required packages are present":このタスクは、pkg_listの下の変数ファイルにリストされているパッケージをインストールします。 変数ファイルは~/ansible-apache/vars/main.ymlにあり、このステップの最後に作成します。
  • "Ensure latest index.html is present":このタスクは、テンプレートページindex.html.j2をコピーし、Apacheによって生成されたデフォルトのインデックスファイル/var/www/html/index.htmlに貼り付けます。 このステップでは、テンプレートも作成します。
  • "Ensure httpd service is started and enabled":このタスクは、変数ファイルのsvc_listにリストされているサービスを開始して有効にします。
  • "Whitelist http in firewalld":このタスクは、firewalldhttpサービスをホワイトリストに登録します。 Firewalldは、CentOSサーバーにデフォルトで存在する完全なファイアウォールソリューションです。 httpサービスを機能させるには、必要なポートを公開する必要があります。 firewalldにサービスをホワイトリストに登録するように指示すると、サービスに必要なすべてのポートがホワイトリストに登録されます。

終了したら、ファイルを保存して閉じます。

次に、index.html.j2テンプレートページ用のtemplatesディレクトリを作成しましょう。

  1. mkdir templates

ページ自体を作成します。

  1. nano templates/index.html.j2

次の定型コードを貼り付けます。

〜/ ansible-apache / templates / index.html.j2
<div style="text-align: center">
    <h2>Managed by Ansible</h2>
</div>

ファイルを保存して閉じます。

ロールを完了するための最後のステップは、変数ファイルを作成することです。このファイルは、メインのロールプレイブックにパッケージとサービスの名前を提供します。

  1. nano vars/main.yml

pkg_listsvc_listを指定する次のコードを使用して、デフォルトのコンテンツを貼り付けます。

〜/ ansible-apache / vars / main.yml
---
pkg_list:
  - httpd
  - firewalld
svc_list:
  - httpd
  - firewalld

これらのリストには、次の情報が含まれています。

  • pkg_list:これには、ロールがインストールするパッケージの名前が含まれています:httpdおよびfirewalld
  • svc_list:これには、役割が開始して有効にするサービスの名前が含まれます:httpdおよびfirewalld

注:変数ファイルに空白行がないことを確認してください。空白行がない場合、リンティング中にテストが失敗します。

ロールの作成が完了したので、意図したとおりに機能するかどうかをテストするようにMoleculeを構成しましょう。

ステップ4—テストを実行するための役割を変更する

この場合、Moleculeを構成するには、Molecule構成ファイルmolecule.ymlを変更してプラットフォーム仕様を追加する必要があります。 httpd systemdサービスを構成して開始するロールをテストしているため、systemdが構成され、特権モードが有効になっているイメージを使用する必要があります。 このチュートリアルでは、DockerHubで利用可能なmilcom/centos7-systemdイメージを使用します。 特権モードでは、コンテナーをホストマシンのほぼすべての機能で実行できます。

molecule.ymlを編集して、これらの変更を反映させましょう。

  1. nano molecule/default/molecule.yml

強調表示されたプラットフォーム情報を追加します。

〜/ ansible-apache /molecule / default /molecule.yml
---
dependency:
  name: galaxy
driver:
  name: docker
lint:
  name: yamllint
platforms:
  - name: centos7
    image: milcom/centos7-systemd
    privileged: true
provisioner:
  name: ansible
  lint:
    name: ansible-lint
scenario:
  name: default
verifier:
  name: testinfra
  lint:
    name: flake8

完了したら、ファイルを保存して閉じます。

テスト環境の構成が正常に完了したので、役割の実行後にMoleculeがコンテナーに対して実行するテストケースの作成に移りましょう。

ステップ5—テストケースの作成

この役割のテストでは、次の条件を確認します。

  • httpdおよびfirewalldパッケージがインストールされていること。
  • httpdおよびfirewalldサービスが実行され、有効になっていること。
  • httpサービスがファイアウォール設定で有効になっていること。
  • そのindex.htmlには、テンプレートファイルで指定されたものと同じデータが含まれています。

これらのテストがすべて合格した場合、役割は意図したとおりに機能します。

これらの条件のテストケースを作成するには、~/ansible-apache/molecule/default/tests/test_default.pyのデフォルトのテストを編集してみましょう。 Testinfraを使用して、Moleculeクラスを使用するPython関数としてテストケースを記述します。

test_default.pyを開きます:

  1. nano molecule/default/tests/test_default.py

ファイルの内容を削除して、テストを最初から作成できるようにします。

注:テストを作成するときは、テストが2行で区切られていることを確認してください。そうしないと、失敗します。

必要なPythonモジュールをインポートすることから始めます。

〜/ ansible-apache /molecule / default / tests / test_default.py
import os
import pytest

import testinfra.utils.ansible_runner

これらのモジュールには次のものが含まれます。

  • os:この組み込みのPythonモジュールは、オペレーティングシステムに依存する機能を有効にし、Pythonが基盤となるオペレーティングシステムとインターフェイスできるようにします。
  • pytestpytestモジュールはテスト書き込みを有効にします。
  • testinfra.utils.ansible_runner:このTestinfraモジュールは、コマンド実行のバックエンドとしてAnsibleを使用します。

モジュールのインポートの下に、次のコードを貼り付けます。このコードは、Ansibleバックエンドを使用して現在のホストインスタンスを返します。

〜/ ansible-apache /molecule / default / tests / test_default.py
...
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')

Ansibleバックエンドを使用するようにテストファイルを構成したら、ホストの状態をテストする単体テストを作成しましょう。

最初のテストでは、httpdfirewalldがインストールされていることを確認します。

〜/ ansible-apache /molecule / default / tests / test_default.py
...

@pytest.mark.parametrize('pkg', [
  'httpd',
  'firewalld'
])
def test_pkg(host, pkg):
    package = host.package(pkg)

    assert package.is_installed

テストはpytest.mark.parametrizeデコレータで始まります。これにより、テストの引数をパラメータ化できます。 この最初のテストでは、[X23X]