Ubuntu18.04でMoleculeを使用してAnsibleロールをテストする方法
著者は、 Write for DOnations プログラムの一環として、 MozillaFoundationを選択して寄付を受け取りました。
序章
Ansible での単体テストは、役割が意図したとおりに機能することを確認するための鍵です。 Molecular は、さまざまな環境に対して役割をテストするシナリオを指定できるようにすることで、このプロセスを容易にします。 Moleculeは、内部でAnsibleを使用して、構成された環境に役割をデプロイするプロビジョナーに役割をオフロードし、ベリファイア( Testinfra など)を呼び出して構成のドリフトをチェックします。 これにより、あなたの役割がその特定のシナリオで環境に予想されるすべての変更を加えたことを確認できます。
このガイドでは、 Apache をホストにデプロイし、CentOS7でfirewalldを構成するAnsibleロールを構築します。 この役割が意図したとおりに機能することをテストするには、 Docker をドライバーとして使用し、サーバーの状態をテストするためのPythonライブラリであるTestinfraを使用してMoleculeでテストを作成します。 MoleculeはDockerコンテナーをプロビジョニングして役割をテストし、Testinfraはサーバーが意図したとおりに構成されていることを確認します。 終了すると、環境間でビルドするための複数のテストケースを作成し、Moleculeを使用してこれらのテストを実行できるようになります。
前提条件
このガイドを開始する前に、次のものが必要です。
- 1つのUbuntu18.04サーバー。 Ubuntu 18.04を使用したサーバーの初期設定ガイドの手順に従って、root以外のsudoユーザーを作成し、パスワードなしでサーバーに接続できることを確認します。
- サーバーにDockerがインストールされています。 Ubuntu 18.04 にDockerをインストールして使用する方法の手順1と2に従います。これには、root以外のユーザーを
docker
グループに追加することも含まれます。 - Python3および
venv
がサーバーにインストールおよび構成されています。 ガイダンスについては、Python3をインストールしてUbuntu18.04サーバーにプログラミング環境をセットアップする方法に従ってください。 - Ansibleプレイブックに精通していること。 レビューについては、 Configuration Management 101:Writing AnsiblePlaybooksを参照してください。
ステップ1—環境の準備
前提条件を満たしている場合は、Python 3、venv
、およびDockerがインストールされ、正しく構成されている必要があります。 まず、AnsiblewithMoleculeをテストするための仮想環境を作成しましょう。
root以外のユーザーとしてログインし、新しい仮想環境を作成することから始めます。
- python3 -m venv my_env
これをアクティブにして、アクションがその環境に制限されていることを確認します。
- source my_env/bin/activate
次に、アクティブ化された環境で、wheel
パッケージをインストールします。これは、pip
がAnsibleのインストールに使用するbdist_wheel
setuptools
拡張機能を提供します。
- python3 -m pip install wheel
これで、molecule
およびdocker
をpip
とともにインストールできます。 Ansibleは、Moleculeの依存関係として自動的にインストールされます。
- python3 -m pip install molecule docker
これらの各パッケージの機能は次のとおりです。
molecule
:これは、役割のテストに使用するメインのMoleculeパッケージです。molecule
をインストールすると、Ansibleが他の依存関係とともに自動的にインストールされ、Ansibleプレイブックを使用して役割とテストを実行できるようになります。docker
:このPythonライブラリは、MoleculeがDockerとのインターフェイスに使用します。 Dockerをドライバーとして使用しているため、これが必要になります。
次に、Moleculeでロールを作成しましょう。
ステップ2—分子での役割の作成
環境を設定したら、Moleculeを使用して、Apacheのインストールをテストするために使用する基本的な役割を作成できます。 この役割は、ディレクトリ構造といくつかの初期テストを作成し、Dockerをドライバーとして指定して、MoleculeがDockerを使用してテストを実行するようにします。
ansible-apache
という新しい役割を作成します。
- molecule init role -r ansible-apache -d docker
-r
フラグは役割の名前を指定し、-d
はドライバーを指定します。ドライバーはテストで使用するMoleculeのホストをプロビジョニングします。
新しく作成されたロールのディレクトリに移動します。
- cd ansible-apache
デフォルトの役割をテストして、Moleculeが正しく設定されているかどうかを確認します。
- molecule test
デフォルトの各テストアクションを一覧表示する出力が表示されます。 テストを開始する前に、Moleculeは構成ファイルmolecule.yml
を検証して、すべてが正常であることを確認します。 また、テストアクションの順序を指定するこのテストマトリックスも出力します。
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
...
役割を作成してテストをカスタマイズしたら、各テストアクションについて詳しく説明します。 今のところ、各テストの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インデックスページを置き換えるために使用する変数ファイルとテンプレートから抽出されます。
引き続きansible-apache
ディレクトリで、nano
またはお気に入りのテキストエディタを使用して、ロールのタスクファイルを作成します。
- nano tasks/main.yml
ファイルがすでに存在していることがわかります。 そこにあるものを削除し、次のコードに置き換えて、必要なパッケージをインストールし、正しいサービス、HTMLのデフォルト、およびファイアウォール設定を有効にします。
---
- 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"
:このタスクは、firewalld
のhttp
サービスをホワイトリストに登録します。 Firewalldは、CentOSサーバーにデフォルトで存在する完全なファイアウォールソリューションです。http
サービスを機能させるには、必要なポートを公開する必要があります。firewalld
にサービスをホワイトリストに登録するように指示すると、サービスに必要なすべてのポートがホワイトリストに登録されます。
終了したら、ファイルを保存して閉じます。
次に、index.html.j2
テンプレートページ用のtemplates
ディレクトリを作成しましょう。
- mkdir templates
ページ自体を作成します。
- nano templates/index.html.j2
次の定型コードを貼り付けます。
<div style="text-align: center">
<h2>Managed by Ansible</h2>
</div>
ファイルを保存して閉じます。
ロールを完了するための最後のステップは、変数ファイルを作成することです。このファイルは、メインのロールプレイブックにパッケージとサービスの名前を提供します。
- nano vars/main.yml
pkg_list
とsvc_list
を指定する次のコードを使用して、デフォルトのコンテンツを貼り付けます。
---
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
を編集して、これらの変更を反映させましょう。
- nano 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
を開きます:
- nano molecule/default/tests/test_default.py
ファイルの内容を削除して、テストを最初から作成できるようにします。
注:テストを作成するときは、テストが2行で区切られていることを確認してください。そうしないと、失敗します。
必要なPythonモジュールをインポートすることから始めます。
import os
import pytest
import testinfra.utils.ansible_runner
これらのモジュールには次のものが含まれます。
os
:この組み込みのPythonモジュールは、オペレーティングシステムに依存する機能を有効にし、Pythonが基盤となるオペレーティングシステムとインターフェイスできるようにします。pytest
:pytestモジュールはテスト書き込みを有効にします。testinfra.utils.ansible_runner
:このTestinfraモジュールは、コマンド実行のバックエンドとしてAnsibleを使用します。
モジュールのインポートの下に、Ansibleバックエンドを使用して現在のホストインスタンスを返す次のコードを追加します。
...
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
Ansibleバックエンドを使用するようにテストファイルを構成したら、ホストの状態をテストする単体テストを作成しましょう。
最初のテストでは、httpd
とfirewalld
がインストールされていることを確認します。
...
@pytest.mark.parametrize('pkg', [
'httpd',
'firewalld'
])
def test_pkg(host, pkg):
package = host.package(pkg)
assert package.is_installed
テストはpytest.mark.parametrizeデコレータで始まります。これにより、テストの引数をパラメータ化できます。 この最初のテストでは、[X23X]