Ubuntu18.04でMoleculeとTravisCIを使用してAnsibleロールの継続的テストを実装する方法
序章
Ansible は、YAMLテンプレートを使用して、ホストで実行されるタスクのリストを定義するエージェントレス構成管理ツールです。 Ansibleでは、 roles は、単一の複雑な機能を実行するために一緒に使用される変数、タスク、ファイル、テンプレート、およびモジュールのコレクションです。
Molecular は、Ansibleの役割の自動テストを実行するためのツールであり、一貫して適切に作成され維持されている役割の開発をサポートするように特別に設計されています。 Moleculeの単体テストを使用すると、開発者は複数の環境に対して、異なるパラメーターで同時に役割をテストできます。 開発者は、頻繁に変更されるコードに対して継続的にテストを実行することが重要です。 このワークフローにより、コードライブラリを更新するときに役割が引き続き機能することが保証されます。 Travis CI などの継続的インテグレーションツールを使用してMoleculeを実行すると、テストを継続的に実行できるため、コードへの貢献によって重大な変更が発生することはありません。
このチュートリアルでは、UbuntuおよびCentOSサーバーにApacheWebサーバーとファイアウォールをインストールして構成する事前に作成された基本ロールを使用します。 次に、そのロールでMoleculeシナリオを初期化してテストを作成し、ターゲット環境でロールが意図したとおりに実行されることを確認します。 Moleculeを構成した後、Travis CIを使用して、新しく作成したロールを継続的にテストします。 コードに変更が加えられるたびに、TravisCIが実行されます molecule test
役割が引き続き正しく実行されることを確認します。
前提条件
このチュートリアルを開始する前に、次のものが必要です。
- Ubuntu 18.04初期サーバーセットアップガイドに従ってセットアップされた1つのUbuntu18.04サーバー(sudo非rootユーザーとファイアウォールを含む)。
- AnsibleとMoleculeが構成されています。これは、 Ubuntu18.04でMoleculeを使用してAnsibleの役割をテストする方法のステップ1に従って実行できます。
- オープンソースに貢献する方法:Gitの使用開始に従ってインストールされたGit。
- 継続的インテグレーションとそのユースケースに精通していること。 詳細については、継続的インテグレーション、デリバリー、およびデプロイメントの概要を確認してください。
- GitHubのアカウント。
- TravisCIのアカウント。
ステップ1—基本ロールリポジトリをフォークする
Apacheをインストールし、DebianベースおよびRedHatベースのディストリビューションにファイアウォールを構成するansible-apacheと呼ばれる事前に作成されたロールを使用します。 この役割をフォークしてベースとして使用し、その上に分子テストを構築します。 Forkingを使用すると、リポジトリのコピーを作成できるため、元のプロジェクトを改ざんすることなくリポジトリに変更を加えることができます。
ansible-apacheロールのフォークを作成することから始めます。 ansible-apache リポジトリに移動し、フォークボタンをクリックします。
リポジトリをフォークすると、GitHubがフォークのページに移動します。 これはベースリポジトリのコピーになりますが、自分のアカウントで行います。
緑色のCloneまたはDownloadボタンをクリックすると、 Clone withHTTPSのボックスが表示されます。
リポジトリに表示されているURLをコピーします。 これは次のステップで使用します。 URLは次のようになります。
https://github.com/username/ansible-apache.git
交換します username
GitHubのユーザー名を使用します。
フォークを設定したら、サーバーにフォークを複製し、次のセクションで役割の準備を開始します。
ステップ2—役割の準備
前提条件のステップ1Ubuntu 18.04 でMoleculeを使用してAnsibleの役割をテストする方法を実行すると、MoleculeとAnsibleが仮想環境にインストールされます。 この仮想環境を使用して、新しい役割を開発します。
まず、以下を実行して、前提条件に従って作成した仮想環境をアクティブ化します。
- source my_env/bin/activate
次のコマンドを実行して、手順1でコピーしたURLを使用してリポジトリのクローンを作成します。
- git clone https://github.com/username/ansible-apache.git
出力は次のようになります。
OutputCloning into 'ansible-apache'...
remote: Enumerating objects: 16, done.
remote: Total 16 (delta 0), reused 0 (delta 0), pack-reused 16
Unpacking objects: 100% (16/16), done.
新しく作成したディレクトリに移動します。
- cd ansible-apache
ダウンロードした基本ロールは、次のタスクを実行します。
-
変数を含める:役割は、ホストの分布に従って、必要なすべての変数を含めることから始まります。 Ansibleは変数を使用して、異なるシステム間の不一致を処理します。 Ubuntu18.04とCentOS7をホストとして使用しているため、ロールはOSファミリーがそれぞれDebianとRed Hatであることを認識し、
vars/Debian.yml
とvars/RedHat.yml
. -
配布関連のタスクが含まれています:これらのタスクには次のものが含まれます
tasks/install-Debian.yml
とtasks/install-RedHat.yml
. 指定されたディストリビューションに応じて、関連するパッケージをインストールします。 Ubuntuの場合、これらのパッケージはapache2
とufw
. CentOSの場合、これらのパッケージはhttpd
とfirewalld
. -
最新のindex.htmlが存在することを確認します:このタスクはテンプレートをコピーします
templates/index.html.j2
ApacheがWebサーバーのホームページとして使用します。 -
関連するサービスを開始し、起動時にそれらを有効にします:最初のタスクの一部としてインストールされた必要なサービスを開始して有効にします。 CentOSの場合、これらのサービスは
httpd
とfirewalld
、そしてUbuntuの場合、それらはapache2
とufw
. -
トラフィックを許可するようにファイアウォールを構成します:これには次のいずれかが含まれます
tasks/configure-Debian-firewall.yml
またtasks/configure-RedHat-firewall.yml
. Ansibleは、FirewalldまたはUFWのいずれかをファイアウォールとして構成し、http
サービス。
この役割がどのように機能するかを理解したので、それをテストするようにMoleculeを構成します。 これらのタスクのテストケースを作成して、それらが行う変更をカバーします。
ステップ3—テストを書く
基本ロールが意図したとおりにタスクを実行することを確認するには、Moleculeシナリオを開始し、ターゲット環境を指定して、3つのカスタムテストファイルを作成します。
次のコマンドを使用して、この役割の分子シナリオを初期化することから始めます。
- molecule init scenario -r ansible-apache
次の出力が表示されます。
Output--> Initializing new scenario default...
Initialized scenario in /home/sammy/ansible-apache/molecule/default successfully.
CentOSとUbuntuをプラットフォームとしてMolecule構成ファイルに含めることにより、ターゲット環境として追加します。 これを行うには、 molecule.yml
テキストエディタを使用したファイル:
- nano molecule/default/molecule.yml
次の強調表示されたコンテンツをMolecule構成に追加します。
---
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
platforms:
- name: centos7
image: milcom/centos7-systemd
privileged: true
- name: ubuntu18
image: solita/ubuntu-systemd
command: /sbin/init
privileged: true
volumes:
- /lib/modules:/lib/modules:ro
provisioner:
name: ansible
lint:
name: ansible-lint
scenario:
name: default
verifier:
name: testinfra
lint:
name: flake8
ここでは、systemdサービスを使用しているため、特権モードで起動される2つのターゲットプラットフォームを指定しています。
centos7
は最初のプラットフォームであり、milcom/centos7-systemd
画像。ubuntu18
2番目のプラットフォームであり、solita/ubuntu-systemd
画像。 特権モードを使用して必要なカーネルモジュールをマウントすることに加えて、実行している/sbin/init
起動時にiptablesが稼働していることを確認します。
ファイルを保存して終了します。
特権コンテナの実行の詳細については、公式のMoleculeドキュメントを参照してください。
デフォルトのMoleculeテストファイルを使用する代わりに、3つのカスタムテストファイルを作成します。1つはターゲットプラットフォームごとに1つ、もう1つはすべてのプラットフォームに共通のテストを作成するためのファイルです。 シナリオのデフォルトのテストファイルを削除することから始めます test_default.py
次のコマンドを使用します。
- rm molecule/default/tests/test_default.py
これで、3つのカスタムテストファイルの作成に進むことができます。 test_common.py
, test_Debian.py
、 と test_RedHat.py
ターゲットプラットフォームごとに。
最初のテストファイル、 test_common.py
、各ホストが実行する一般的なテストが含まれます。 共通のテストファイルを作成および編集し、 test_common.py
:
- nano molecule/default/tests/test_common.py
次のコードをファイルに追加します。
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
@pytest.mark.parametrize('file, content', [
("/var/www/html/index.html", "Managed by Ansible")
])
def test_files(host, file, content):
file = host.file(file)
assert file.exists
assert file.contains(content)
あなたの中で test_common.py
ファイル、必要なライブラリをインポートしました。 あなたはまた、というテストを書きました test_files()
、これは、ロールが実行するディストリビューション間の唯一の共通タスクを保持します。つまり、テンプレートをWebサーバーのホームページとしてコピーします。
次のテストファイル、 test_Debian.py
、Debianディストリビューションに固有のテストを保持します。 このテストファイルは、特にUbuntuプラットフォームを対象としています。
次のコマンドを実行して、Ubuntuテストファイルを作成および編集します。
- nano molecule/default/tests/test_Debian.py
これで、必要なライブラリをインポートして、 ubuntu18
ターゲットホストとしてのプラットフォーム。 このファイルの先頭に次のコードを追加します。
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('ubuntu18')
次に、同じファイルに追加します test_pkg()
テスト。
次のコードをファイルに追加します。これにより、 test_pkg()
テスト:
...
@pytest.mark.parametrize('pkg', [
'apache2',
'ufw'
])
def test_pkg(host, pkg):
package = host.package(pkg)
assert package.is_installed
このテストでは、 apache2
と ufw
パッケージはホストにインストールされます。
注: Moleculeテストファイルに複数のテストを追加する場合は、各テストの間に2つの空白行があることを確認してください。そうしないと、Moleculeから構文エラーが発生します。
次のテストを定義するには、 test_svc()
、下に次のコードを追加します test_pkg()
ファイルでテストします。
...
@pytest.mark.parametrize('svc', [
'apache2',
'ufw'
])
def test_svc(host, svc):
service = host.service(svc)
assert service.is_running
assert service.is_enabled
test_svc()
かどうかを確認します apache2
と ufw
サービスが実行され、有効になっています。
最後に、最後のテストを追加します。 test_ufw_rules()
、へ test_Debian.py
ファイル。
このコードを下に追加します test_svc()
ファイルをテストして定義する test_ufw_rules()
:
...
@pytest.mark.parametrize('rule', [
'-A ufw-user-input -p tcp -m tcp --dport 80 -j ACCEPT'
])
def test_ufw_rules(host, rule):
cmd = host.run('iptables -t filter -S')
assert rule in cmd.stdout
test_ufw_rules()
ファイアウォール構成がApacheサービスによって使用されるポートでのトラフィックを許可することを確認します。
これらの各テストを追加すると、 test_Debian.py
ファイルは次のようになります。
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('ubuntu18')
@pytest.mark.parametrize('pkg', [
'apache2',
'ufw'
])
def test_pkg(host, pkg):
package = host.package(pkg)
assert package.is_installed
@pytest.mark.parametrize('svc', [
'apache2',
'ufw'
])
def test_svc(host, svc):
service = host.service(svc)
assert service.is_running
assert service.is_enabled
@pytest.mark.parametrize('rule', [
'-A ufw-user-input -p tcp -m tcp --dport 80 -j ACCEPT'
])
def test_ufw_rules(host, rule):
cmd = host.run('iptables -t filter -S')
assert rule in cmd.stdout
The test_Debian.py
ファイルには、次の3つのテストが含まれています。 test_pkg()
, test_svc()
、 と test_ufw_rules()
.
保存して終了 test_Debian.py
.
次に、を作成します test_RedHat.py
テストファイル。CentOSプラットフォームを対象とするRedHatディストリビューションに固有のテストが含まれます。
CentOSテストファイルを作成および編集し、 test_RedHat.py
、次のコマンドを実行します。
- nano molecule/default/tests/test_RedHat.py
Ubuntuテストファイルと同様に、3つのテストを記述して test_RedHat.py
ファイル。 テストコードを追加する前に、必要なライブラリをインポートして、 centos7
ファイルの先頭に次のコードを追加して、ターゲットホストとしてプラットフォームを作成します。
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('centos7')
次に、 test_pkg()
テスト。 httpd
と firewalld
パッケージはホストにインストールされます。
ライブラリインポートのコードに従って、 test_pkg()
ファイルをテストします。 (繰り返しますが、新しいテストの前に2つの空白行を含めることを忘れないでください。)
...
@pytest.mark.parametrize('pkg', [
'httpd',
'firewalld'
])
def test_pkg(host, pkg):
package = host.package(pkg)
assert package.is_installed
今、あなたは追加することができます test_svc()
テストして次のことを確認します httpd
と firewalld
サービスが実行され、有効になっています。
追加します test_svc()
次のファイルへのコード test_pkg()
テスト:
...
@pytest.mark.parametrize('svc', [
'httpd',
'firewalld'
])
def test_svc(host, svc):
service = host.service(svc)
assert service.is_running
assert service.is_enabled
の最終テスト test_RedHat.py
ファイルは test_firewalld()
、Firewalldに http
サービスがホワイトリストに登録されました。
追加します test_firewalld()
後にファイルをテストします test_svc()
コード:
...
@pytest.mark.parametrize('file, content', [
("/etc/firewalld/zones/public.xml", "<service name=\"http\"/>")
])
def test_firewalld(host, file, content):
file = host.file(file)
assert file.exists
assert file.contains(content)
ライブラリをインポートして3つのテストを追加した後、 test_RedHat.py
ファイルは次のようになります。
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('centos7')
@pytest.mark.parametrize('pkg', [
'httpd',
'firewalld'
])
def test_pkg(host, pkg):
package = host.package(pkg)
assert package.is_installed
@pytest.mark.parametrize('svc', [
'httpd',
'firewalld'
])
def test_svc(host, svc):
service = host.service(svc)
assert service.is_running
assert service.is_enabled
@pytest.mark.parametrize('file, content', [
("/etc/firewalld/zones/public.xml", "<service name=\"http\"/>")
])
def test_firewalld(host, file, content):
file = host.file(file)
assert file.exists
assert file.contains(content)
3つのファイルすべてでテストの記述が完了したので、 test_common.py
, test_Debian.py
、 と test_RedHat.py
、あなたの役割はテストの準備ができています。 次のステップでは、Moleculeを使用して、新しく構成されたロールに対してこれらのテストを実行します。
ステップ4—自分の役割に対するテスト
次に、基本ロールに対して新しく作成したテストを実行します ansible-apache
分子を使用します。 テストを実行するには、次のコマンドを使用します。
- molecule test
Moleculeがすべてのテストの実行を終了すると、次の出力が表示されます。
Output...
--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in /home/sammy/ansible-apache/molecule/default/tests/...
============================= test session starts ==============================
platform linux -- Python 3.6.7, pytest-4.1.1, py-1.7.0, pluggy-0.8.1
rootdir: /home/sammy/ansible-apache/molecule/default, inifile:
plugins: testinfra-1.16.0
collected 12 items
tests/test_common.py .. [ 16%]
tests/test_RedHat.py ..... [ 58%]
tests/test_Debian.py ..... [100%]
========================== 12 passed in 80.70 seconds ==========================
Verifier completed successfully.
わかるでしょ Verifier completed successfully
出力で; これは、ベリファイアがすべてのテストを実行し、それらを正常に返したことを意味します。
役割の開発が正常に完了したので、変更をGitにコミットし、継続的テスト用にTravisCIをセットアップできます。
ステップ5—Gitを使用して更新された役割を共有する
このチュートリアルでは、これまでに、という役割のクローンを作成しました。 ansible-apache
そして、UbuntuおよびCentOSホストに対して機能することを確認するためのテストを追加しました。 更新された役割を一般の人々と共有するには、これらの変更をコミットしてフォークにプッシュする必要があります。
次のコマンドを実行してファイルを追加し、行った変更をコミットします。
- git add .
このコマンドは、現在のディレクトリで変更したすべてのファイルをステージング領域に追加します。
また、名前とメールアドレスをで設定する必要があります git config
正常にコミットするために。 次のコマンドを使用してこれを行うことができます。
- git config user.email "[email protected]"
- git config user.name "John Doe"
変更したファイルをリポジトリにコミットします。
- git commit -m "Configured Molecule"
次の出力が表示されます。
Output[master b2d5a5c] Configured Molecule
8 files changed, 155 insertions(+), 1 deletion(-)
create mode 100644 molecule/default/Dockerfile.j2
create mode 100644 molecule/default/INSTALL.rst
create mode 100644 molecule/default/molecule.yml
create mode 100644 molecule/default/playbook.yml
create mode 100644 molecule/default/tests/test_Debian.py
create mode 100644 molecule/default/tests/test_RedHat.py
create mode 100644 molecule/default/tests/test_common.py
これは、変更が正常にコミットされたことを意味します。 次に、次のコマンドを使用して、これらの変更をフォークにプッシュします。
- git push -u origin master
GitHubクレデンシャルの入力を求めるプロンプトが表示されます。 これらの資格情報を入力すると、コードがリポジトリにプッシュされ、次の出力が表示されます。
OutputCounting objects: 13, done.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (13/13), 2.32 KiB | 2.32 MiB/s, done.
Total 13 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 2 local objects.
To https://github.com/username/ansible-apache.git
009d5d6..e4e6959 master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
あなたがあなたのフォークのリポジトリに行くなら github.com/username/ansible-apache
、という新しいコミットが表示されます Configured Molecule
ファイルに加えた変更を反映します。
これで、Travis CIを新しいリポジトリと統合して、役割に加えられた変更によってMoleculeテストが自動的にトリガーされるようになりました。 これにより、あなたの役割が常にUbuntuおよびCentOSホストで機能するようになります。
ステップ6—TravisCIの統合
このステップでは、TravisCIをワークフローに統合します。 有効にすると、フォークにプッシュする変更があれば、TravisCIビルドがトリガーされます。 これの目的は、TravisCIが常に実行されるようにすることです。 molecule test
寄稿者が変更を加えるときはいつでも。 重大な変更が加えられた場合、Travisはビルドステータスをそのように宣言します。
Travis CI に進み、リポジトリを有効にします。 GitHubのActivateボタンをクリックできるプロファイルページに移動します。
TravisCIでのリポジトリのアクティブ化に関する詳細なガイダンスここを見つけることができます。
Travis CIを機能させるには、その手順を含む構成ファイルを作成する必要があります。 Travis構成ファイルを作成するには、サーバーに戻り、次のコマンドを実行します。
- nano .travis.yml
このチュートリアルで作成した環境を複製するには、Travis構成ファイルでパラメーターを指定します。 次のコンテンツをファイルに追加します。
---
language: python
python:
- "2.7"
- "3.6"
services:
- docker
install:
- pip install molecule docker
script:
- molecule --version
- ansible --version
- molecule test
このファイルで指定したパラメーターは次のとおりです。
language
:言語としてPythonを指定すると、CI環境は個別に使用しますvirtualenv
下で指定する各Pythonバージョンのインスタンスpython
鍵。python
:ここでは、TravisがPython2.7とPython3.6の両方を使用してテストを実行することを指定しています。services
:Moleculeでテストを実行するにはDockerが必要です。 TravisがDockerがCI環境に存在することを確認する必要があることを指定しています。install
:ここでは、TravisCIが実行する予備インストール手順を指定していますvirtualenv
.pip install molecule docker
AnsibleとMoleculeがDockerリモートAPIのPythonライブラリと一緒に存在することを確認します。
script
:これは、TravisCIが実行する必要のあるステップを指定するためのものです。 ファイルでは、次の3つのステップを指定しています。molecule --version
Moleculeが正常にインストールされている場合は、Moleculeバージョンを出力します。ansible --version
Ansibleが正常にインストールされている場合は、Ansibleバージョンを出力します。molecule test
最後に、分子テストを実行します。
指定する理由 molecule --version
と ansible --version
次の結果としてビルドが失敗した場合にエラーをキャッチすることです ansible
また molecule
バージョン管理による設定ミス。
コンテンツをTravisCI構成ファイルに追加したら、保存して終了します .travis.yml
.
これで、リポジトリに変更をプッシュするたびに、TravisCIは上記の構成ファイルに基づいてビルドを自動的に実行します。 のコマンドのいずれかが script
ブロックが失敗すると、TravisCIはビルドステータスをそのように報告します。
ビルドステータスを簡単に確認できるように、ビルドステータスを示すバッジをに追加できます。 README
あなたの役割の。 を開きます README.md
テキストエディタを使用したファイル:
- nano README.md
次の行をに追加します README.md
ビルドステータスを表示するには:
[](https://travis-ci.org/username/ansible-apache)
交換 username
GitHubのユーザー名を使用します。 以前と同じように、変更をコミットしてリポジトリにプッシュします。
まず、次のコマンドを実行して追加します .travis.yml
と README.md
ステージングエリアへ:
- git add .travis.yml README.md
次に、以下を実行して、変更をリポジトリにコミットします。
- git commit -m "Configured Travis"
最後に、次のコマンドを使用して、これらの変更をフォークにプッシュします。
- git push -u origin master
GitHubリポジトリに移動すると、最初に build:unknownが報告されていることがわかります。
数分以内に、TravisはTravisCIWebサイトで監視できるビルドを開始します。 ビルドが成功すると、GitHubはリポジトリにもステータスを報告します—READMEファイルに配置したバッジを使用します。
Travis CI Webサイトにアクセスすると、ビルドの完全な詳細にアクセスできます。
新しいロール用にTravisCIを正常にセットアップしたので、Ansibleロールへの変更を継続的にテストして統合できます。
結論
このチュートリアルでは、GitHubからApache Webサーバーをインストールして構成する役割をフォークし、UbuntuとCentOSを実行しているDockerコンテナーで動作するようにテストを記述し、これらのテストを構成することでMoleculeの統合を追加しました。 新しく作成したロールをGitHubにプッシュすることで、他のユーザーが自分のロールにアクセスできるようになります。 コントリビューターによってロールに変更があった場合、TravisCIは自動的にMoleculeを実行してロールをテストします。
ロールの作成とMoleculeでのテストに慣れたら、これを Ansible Galaxy と統合して、ビルドが成功するとロールが自動的にプッシュされるようにすることができます。