やっさん的Ansible role開発をmolecule使って始めるテンプレ

adventar.org この記事は、上記の6日目の記事です。

ロールを追加する際に、 molecule を使うと非常に便利です。テスト(verify)を書かないにしても、テストドライバーを使ってdockerやvagrantなどの仮想環境にroleを適用してみて途中でエラーになったり、templateの生成が想定が違うなどを実際に確認出来るので、まずははじめることをオススメします。

いつもroleを作成する際にやってる一連の流れを紹介。 XXは〇〇すると良いよ!など、アドバイスあれば教えて下さい!

前提

OS:CentOS7 or Ubuntu 20.04 LTS

molecule 3.2.1 using python 3.8 
    ansible:2.10.4
    delegated:3.2.1 from molecule
    docker:0.2.4 from molecule_docker
    vagrant:0.6.1 from molecule_vagrant

また、roleを含むリポジトリRoles — Ansible Documentation にあるように以下の構成とします。

# playbooks
site.yml
group_vars/
    group_xxx/
host_vars/
    xxxx.example.com/
roles/
    xxx/
        defaults/
        files/
        handlers/
        library/
        meta/
        tasks/
        templates/
        vars/
    yyy/
     :

初期構築

Installation — Molecule documentation を参考に、OSに合せて必要なpackageをインストール。

$ sudo yum install -y gcc python3-pip python3-devel openssl-devel python3-libselinux

仮想環境(venv)の用意

実行するansibleのバージョンやroleやmoduleで利用するpipが異ならないように仮想環境を用意して合わせるようにします(追加するpipはansibleを含め requirements.txt に定義します)。

とは言え、venvの用意が毎度めんどいので、以下の様にMakefileを用意して make init-molecule で準備できるようにします。 また、ついでに、バージョンチェックしてコマンド実行時にエラーにならないか簡単にチェックしています。

これは、CIなどからも呼び出しすると簡略化出来るので便利。

SHELL=/bin/bash

# 初回構築用
.PHONY: init-molecule
init-molecule:
    python3 -m venv .venv && .venv/bin/pip install --upgrade pip && .venv/bin/pip install -r requirements.txt
    .venv/bin/pip --version ;
    source .venv/bin/activate && \
    .venv/bin/molecule --version && \
    .venv/bin/ansible --version && \
    deactivate

参考:私がよく使ってる requirements.txt はこちら。

ansible ~= 2.10.0
cryptography
jmespath
pyyaml

setuptools
virtualenv

ansible-lint
molecule[lint]
molecule-docker
molecule-vagrant

※自分の組織合せて、ansibleだけでなく ansible-lint や molecule* についてはバージョンを固定することを推奨します(特にCIとは同じにしておく方が良いです)。

始めるとき

始めるときは以下の流れではじめてます。

# roleのリポジトリに入る
$ make init-molecule
$ source .venv/bin/activate

(何らかの対応)

# 終わる場合
$ deavtivate

roleのテンプレを使って初回分を作成

moleculeにはroleのテンプレを作成するコマンドが以下の通り存在しています。

$ molecule init role --help
Usage: molecule init role [OPTIONS] ROLE_NAME

  Initialize a new role for use with Molecule.

Options:
  --dependency-name [galaxy]      Name of dependency to initialize. (galaxy)
  -d, --driver-name [delegated|docker|vagrant]
                                  Name of driver to initialize. (delegated)
  --lint-name [yamllint]          Name of lint to initialize. (yamllint)
  --provisioner-name [ansible]    Name of provisioner to initialize. (ansible)
  --verifier-name [ansible|testinfra]
                                  Name of verifier to initialize. (ansible)
  --help                          Show this message and exit.

なので、 roles/ に移動後に以下の様に初回分を作成します。

# `role` があるディレクトリまで移動
$ cd roles

# defaultシナリオのテストドライバーは Docker、テストの記述は Ansible の場合 ※通常はこっち
$  molecule init role new_role -d docker --verifier-name ansible --dependency-name galaxy

# defaultシナリオのテストドライバーは vagrant、テストの記述は Ansible の場合
$  molecule init role new_role -d vagrant --verifier-name ansible --dependency-name galaxy

# defaultシナリオのテストドライバーは Docker、テストの記述は Testinfra の場合
$  molecule init role new_role -d docker --verifier-name testinfra --dependency-name galaxy

とまぁ、面倒くさいので以下の様にMakefileに追加します。

:
driver            := docker
 :
# 新規role追加
# # ex) make add-role role=hoge driver=vagrant
.PHONY: add-role
add-role:
    cd roles && molecule init role $(role) -d $(driver) --verifier-name ansible --dependency-name galaxy

すると、 site.yml がある場所( roles/ と同じ階層 )にて、hugaロールを追加したい場合は以下のようにするだけになります。

# defaultシナリオのテストドライバーは Docker、テストの記述は Ansible の場合
make add-role role=huga

roleにシナリオを追加する場合

デフォルト以外のシナリオを追加したい場合も同様にmoleculeコマンド使います。

$ molecule init scenario --help
Usage: molecule init scenario [OPTIONS] [SCENARIO_NAME]

  Initialize a new scenario for use with Molecule.

  If name is not specified the 'default' value will be used.

Options:
  --dependency-name [galaxy]      Name of dependency to initialize. (galaxy)
  -d, --driver-name [delegated|docker|vagrant]
                                  Name of driver to initialize. (delegated)
  --lint-name [yamllint]          Name of lint to initialize. (ansible-lint)
  --provisioner-name [ansible]    Name of provisioner to initialize. (ansible)
  -r, --role-name TEXT            Name of the role to create.
  --verifier-name [ansible|testinfra]
                                  Name of verifier to initialize. (ansible)
  --help                          Show this message and exit.

なので、以下のようにして追加出来ます

# 「driver: docker、verifier: ansible、シナリオ名:piyo」の場合
$ molecule init scenario -d docker --verifier-name ansible --dependency-name galaxy piyo

# 「driver: vagrant、verifier: testinfra、シナリオ名:vagrant」の場合
$ molecule init scenario -d vagrant --verifier-name testinfra --dependency-name galaxy vagrant

また、CIの場合など特定のシナリオだけ実行したい場合を考慮して、 ロール以下で、 make test だけで実行出来るように、ロール直下に以下のようなMakefileを作成しています。

SHELL=/bin/bash

# 複数シナリオの場合にはここに半角スペースでシナリオ名をつなげていく
TEST_SCENARIO      := default

.PHONY: test
test:
    for TEST in $(TEST_SCENARIO); do\
        molecule test -s $$TEST --destroy always; \
    done

こうすることで TEST_SCENARIOTEST_SCENARIO := default piyo のようにして、defaultとpiyoシナリオだけ実行する事が make test だけで簡単に出来るようになります(CIではvagrantのシナリオは実行したくないとか)。

さいごに

今回紹介した以外にも、 Ansible Galaxyを使った開発方法もあります。
cf. Galaxy Developer Guide — Ansible Documentation

ただ、 v2.9 から正式に使えるようになったroleやmodule、pluginも含めた Collections と、これまであったroleのみのものもあってroleは消えていくのか?それとも共存するのかよく分からないので詳しいひと教えて下さい(ぁ

あと、公開できない roleやcollections の場合、AWXと組み合わせて使うにはどうするのか?とか。。。

以上、 Ansible Advent Calendar 2020 - Adventar の6日目の記事でした。

参考

最終的なMakefle

リポジトリ直下のMakefile

SHELL=/bin/bash

.PHONY: init-molecule
init-molecule:
    python3 -m venv .venv && .venv/bin/pip install --upgrade pip && .venv/bin/pip install -r requirements.txt
    .venv/bin/pip --version ;
    source .venv/bin/activate && \
    .venv/bin/molecule --version && \
    .venv/bin/ansible --version && \
    deactivate

各ロール直下のMakefile

SHELL=/bin/bash

# 複数シナリオの場合にはここに半角スペースでシナリオ名をつなげていく
TEST_SCENARIO      := default

.PHONY: test
test:
    for TEST in $(TEST_SCENARIO); do\
        molecule test -s $$TEST --destroy always; \
    done

作成したロールのディレクトリツリー

        :
├── Makefile
├── roles
│   └── new_role
│       ├── Makefile
│       ├── README.md
│       ├── defaults
│       │   └── main.yml
│       ├── files
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       │   └── main.yml
│       ├── molecule
│       │   ├── default
│       │   │   ├── converge.yml
│       │   │   ├── molecule.yml
│       │   │   └── verify.yml
│       │   └── piyo
│       │       ├── converge.yml
│       │       ├── molecule.yml
│       │       └── verify.yml
│       ├── tasks
│       │   └── main.yml
│       ├── templates
│       ├── tests
│       │   ├── inventory
│       │   └── test.yml
│       └── vars
│           └── main.yml
└── site.yml