これは、なにをしたくて書いたもの?
Moleculeが3.0になっていたので、1度試しておこうかなと。
前に試した時は、2.22でした。
Ansible Roleを開発、テストするためのMoleculeを試す - CLOVER🍀
Changelogを見ると、だいぶ変わったみたいです。
特に大きな変更は、以下あたりです(Changelogの「MAJOR」から抜粋)。
- Ansibleのバージョンサポート範囲がN/N-1(たとえば2.9と2.8)になる
- Providerはインストール可能なドライバー、Pythonモジュールになった
- コアから、Azure、EC2、DigitalOcean、GCE、HetznerCloud、Linode、LXD、OpenStack、Vagrantの各Providerが削除
- goss verifierを削除
- playbook.ymlという名前は非推奨になり、converge.ymlに
- デフォルトのverifierがAnsibleになった
- Testinfraはデフォルトでインストールされなくなった
- Scenerio名が設定から削除された
- Lintingの設定がリファクタリングされた
- DockerfileのテンプレートがMolecureに組み込み可能になった
Migrating to molecule v3 checklist · Issue #2560 · ansible-community/molecule · GitHub
Providerがだいぶ削除されたり、Testinfraが入らなくなったりしたんですねぇ。
とりあえず、今回は2.22の時に試した内容を、3.0に読み替えてやってみようと思います。
Moleculeとは
少しだけ、振り返っておきます。
Ansible Molecule — Molecule 3.0.3.dev73+gcc0c7634 documentation
Moleculeは、Ansible Roleを作ったりテストするためのプロジェクトです。
Molecule project is designed to aid in the development and testing of Ansible roles.
複数のインスタンス、OS、仮想化プロバイダー、テストに関するサポートを提供するものです。
Molecule provides support for testing with multiple instances, operating systems and distributions, virtualization providers, test frameworks and testing scenarios.
環境
今回の環境は、こちらです。
$ python3 -V Python 3.6.9 $ pip3 -V pip 9.0.1 from /path/to/venv/lib/python3.6/site-packages (python 3.6)
インストール
まずは、Moleculeをインストールします。
Installation — Molecule 3.0.3.dev73+gcc0c7634 documentation
$ pip3 install molecule[lint]
インストールしたバージョン。
$ pip3 freeze | grep -E 'ansible|molecule' ansible==2.9.6 ansible-lint==4.2.0 molecule==3.0.2
試してみる
Getting Startedを見つつ、Moleculeを試していきます。
Getting Started Guide — Molecule 3.0.3.dev73+gcc0c7634 documentation
お題としては、ApacheをインストールするRoleを作ることにしましょう。
「molecule init」でRoleを作成。
$ molecule init role apache
できあがったファイル。
$ find apache -type f apache/handlers/main.yml apache/README.md apache/vars/main.yml apache/.travis.yml apache/meta/main.yml apache/defaults/main.yml apache/tests/inventory apache/tests/test.yml apache/tasks/main.yml apache/molecule/default/verify.yml apache/molecule/default/converge.yml apache/molecule/default/molecule.yml apache/molecule/default/INSTALL.rst apache/.yamllint
いくつか、見ていきましょう。
定義内容は、Configuration Guideを見つつ。
Configuration — Molecule 3.0.3.dev73+gcc0c7634 documentation
Moleculeの中心となる設定ファイルです。
apache/molecule/default/molecule.yml
--- dependency: name: galaxy driver: name: docker platforms: - name: instance image: docker.io/pycontribs/centos:7 pre_build_image: true provisioner: name: ansible verifier: name: ansible
Changelogにもあったとおり、playbook.ymlはconverge.ymlになったんですね。
apache/molecule/default/converge.yml
--- - name: Converge hosts: all tasks: - name: "Include apache" include_role: name: "apache"
デフォルトのVerifierがAnsibleになったので、verify.ymlというファイルが生成されています。
apache/molecule/default/verify.yml
--- # This is an example playbook to execute Ansible tests. - name: Verify hosts: all tasks: - name: Example assertion assert: that: true
assertモジュールで検証します、と。
assert – Asserts given expressions are true — Ansible Documentation
作成されたRoleのディレクトリに移動。
$ cd apache
DockerイメージはpysのCentOSでしたが、今回はUbuntu Linuxを使うことにしましょう。
pysというのは、メジャーなOSでPythonを有効化してビルドされたDockerイメージです。
こんな感じに変更。
driver: name: docker platforms: - name: instance image: docker.io/pycontribs/ubuntu:latest pre_build_image: true dns_servers: - 8.8.8.8
「dns_servers」を指定しているのは、aptでApacheをインストールする時に名前解決ができなくてエラーになったからです…。
Err:1 http://archive.ubuntu.com/ubuntu bionic InRelease Temporary failure resolving 'archive.ubuntu.com' Err:2 http://security.ubuntu.com/ubuntu bionic-security InRelease Temporary failure resolving 'security.ubuntu.com' Err:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease Temporary failure resolving 'archive.ubuntu.com' Err:4 http://archive.ubuntu.com/ubuntu bionic-backports InRelease Temporary failure resolving 'archive.ubuntu.com'
では、プロビジョニングを行うインスタンスを作成します。
「molecule create」でインスタンスの作成…ですが、エラーになります。
$ molecule create --> Test matrix └── default ├── dependency ├── create └── prepare --> Scenario: 'default' --> Action: 'dependency' Skipping, missing the requirements file. --> Scenario: 'default' --> Action: 'create' --> Sanity checks: 'docker' ERROR: Missing Docker driver dependency. Please install via 'molecule[docker]' or refer to your INSTALL.rst driver documentation file
「Dockerドライバがない」と言われているので、インストール。
$ pip3 install molecule[docker]
バージョン。
$ pip3 freeze | grep -E 'ansible|molecule|docker' ansible==2.9.6 ansible-lint==4.2.0 docker==4.2.0 molecule==3.0.2
再度、「molecule create」。
$ molecule create
今度は成功します。
$ molecule create --> Test matrix └── default ├── dependency ├── create └── prepare --> Scenario: 'default' --> Action: 'dependency' Skipping, missing the requirements file. --> Scenario: 'default' --> Action: 'create' --> Sanity checks: 'docker' PLAY [Create] ****************************************************************** TASK [Log into a Docker registry] ********************************************** skipping: [localhost] => (item=None) TASK [Check presence of custom Dockerfiles] ************************************ ok: [localhost] => (item=None) ok: [localhost] TASK [Create Dockerfiles from image names] ************************************* skipping: [localhost] => (item=None) TASK [Discover local Docker images] ******************************************** ok: [localhost] => (item=None) ok: [localhost] TASK [Build an Ansible compatible image (new)] ********************************* skipping: [localhost] => (item=molecule_local/docker.io/pycontribs/ubuntu:latest) TASK [Create docker network(s)] ************************************************ TASK [Determine the CMD directives] ******************************************** ok: [localhost] => (item=None) ok: [localhost] TASK [Create molecule instance(s)] ********************************************* changed: [localhost] => (item=instance) TASK [Wait for instance(s) creation to complete] ******************************* FAILED - RETRYING: Wait for instance(s) creation to complete (300 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (299 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (298 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (297 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (296 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (295 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (294 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (293 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (292 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (291 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (290 retries left). FAILED - RETRYING: Wait for instance(s) creation to complete (289 retries left). changed: [localhost] => (item=None) changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=5 changed=2 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0 --> Scenario: 'default' --> Action: 'prepare' Skipping, prepare playbook not configured.
インスタンスの一覧を確認。
$ molecule list Instance Name Driver Name Provisioner Name Scenario Name Created Converged --------------- ------------- ------------------ --------------- --------- ----------- instance docker ansible default true false
当然のことながら、dockerコマンドでも確認できます。
$ docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ba6732094f07 pycontribs/ubuntu:latest "bash -c 'while true…" 56 seconds ago Up 40 seconds instance
起動中のインスタンスにログインするには、「molecule login」で。
$ molecule login root@instance:/#
Ubuntu Linux 18.04 LTSですね。
# uname -a Linux instance 4.18.0-25-generic #26~18.04.1-Ubuntu SMP Thu Jun 27 07:28:31 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux # lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.4 LTS Release: 18.04 Codename: bionic
インスタンスの破棄。
$ molecule destroy
破棄の様子。
$ molecule destroy --> Test matrix └── default ├── dependency ├── cleanup └── destroy --> Scenario: 'default' --> Action: 'dependency' Skipping, missing the requirements file. --> Scenario: 'default' --> Action: 'cleanup' Skipping, cleanup playbook not configured. --> Scenario: 'default' --> Action: 'destroy' --> Sanity checks: 'docker' PLAY [Destroy] ***************************************************************** TASK [Destroy molecule instance(s)] ******************************************** changed: [localhost] => (item=instance) TASK [Wait for instance(s) deletion to complete] ******************************* FAILED - RETRYING: Wait for instance(s) deletion to complete (300 retries left). changed: [localhost] => (item=None) changed: [localhost] TASK [Delete docker network(s)] ************************************************ PLAY RECAP ********************************************************************* localhost : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 --> Pruning extra files from scenario ephemeral directory
では、ApacheをインストールするようにAnsible Roleを作成しましょう。tasks/main.ymlに、以下のように記述。
tasks/main.yml
--- - name: install apache2 apt: name: apache2 state: present update_cache: yes
「molecule converge」で、インスタンスの作成とAnsible Playbookの実行を行います。
$ molecule converge
実行されるのは、coverage.ymlの内容ですね。
molecule/default/converge.yml
--- - name: Converge hosts: all tasks: - name: "Include apache" include_role: name: "apache"
Playbookが実行されている様子。
--> Scenario: 'default' --> Action: 'prepare' Skipping, prepare playbook not configured. --> Scenario: 'default' --> Action: 'converge' PLAY [Converge] **************************************************************** TASK [Gathering Facts] ********************************************************* ok: [instance] TASK [Include apache] ********************************************************** TASK [apache : install apache2] ************************************************ changed: [instance] PLAY RECAP ********************************************************************* instance : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
次は、テスト(Verify)を行ってみましょう。
ところで、MoleculeのデフォルトのVerifierはTestinfraからAnsibleに変わったようですが、それはどうしてかちょっと見てみました。
Make Ansible default verifier · Issue #2013 · ansible-community/molecule · GitHub
使うテクノロジーを、YAMLに統一したかったみたいですね。でも、AnsibleのassertはTestinfraと比べるとどうなのという話もあり…。
デフォルトのverify.ymlを、もう1度見てみます。
molecule/default/verify.yml
--- # This is an example playbook to execute Ansible tests. - name: Verify hosts: all tasks: - name: Example assertion assert: that: true
ここからどう変えていいかちょっとわからなくなったので、今回はTestinfraに切り替えることにしました。
Testinfraとpytestをインストールします。
$ pip3 install testinfra pytest
バージョン。
pip3 freeze | grep -E 'testinfra|pytest' pytest==5.4.1 testinfra==5.0.0
molecule.ymlのVerifierの設定を、AnsibleからTestinfraへ切り替えます。
verifier: # name: ansible name: testinfra
テストコードを置くディレクトリを作成。
$ mkdir molecule/default/tests
作成したテストコード。
molecule/default/tests/test_apache.py
import os import testinfra.utils.ansible_runner testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE'] ).get_hosts('all') def test_apache_is_installed(host): apache2 = host.package('apache2') assert apache2.is_installed
インスタンスが起動している状態であれば、「molecule verify」でテストを行うことができます。
$ molecule verify
こんな感じで。
$ molecule verify --> Test matrix └── default └── verify --> Scenario: 'default' --> Action: 'verify' --> Executing Testinfra tests found in /path/to/apache/molecule/default/tests/... ============================= test session starts ============================== platform linux -- Python 3.6.9, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 rootdir: /path/to/apache/molecule/default plugins: testinfra-5.0.0 collected 1 item tests/test_default.py . [100%] ============================== 1 passed in 5.26s =============================== Verifier completed successfully.
終わったら、インスタンスを破棄しておきましょう。
$ molecule destroy
ここまでの、インスタンスの作成、Playbookの実行、テスト、インスタンスの破棄まで一気に行う場合は、「molecule test」を
実行します。
$ molecule test
こんな感じで、Moleculeのイントロ的な内容を、ざっくり確認してみました。
Molecule 2から3で、テストまわりが変わっていたり、ドライバがなくなっていたりでなかなかビックリしました。