[Ansible]Molecule v6のdefaultドライバを使ってpodmanでテストしてみる

# はじめに

2023/8/14にMolecule 6がリリースされました。

本リリースの変更点は[リリースページ](https://github.com/ansible/molecule/releases/tag/v6.0.0)に詳細がありますが、大きなものは以下の通りです。

1. Playbook実行前のカレントディレクトリをシナリオ配下にする
2. 外部ドライバーを一時的にサポートしない
3. initコマンドを整理
4. dependencyの`collections-path`と`roles-path`を削除

この中の`2. 外部ドライバーを一時的にサポートしない`は前々からかなり話題になっていました。

現在Moleculeでは、[molecule-plugins](https://github.com/ansible-community/molecule-plugins)でEC2やpodmanを用意にテスト環境として使えるプラグインを提供しています。

それがサポートされなくなり、`default`ドライバ(今まで`delegated`ドライバと言っていたもの)内で開発者側がAnsibleテスト環境を用意することになります。

筆者もpodmanを使ってLinuxテスト環境を構築していており、影響がありそうなので
今回Molecule v6でコンテナを使ったテストがうまくできるかを検証してみました。

# 検証

## 概要

Molecule v5とv6でpodmanを使ったRoleテストを行って以下確認します。

- 設定差分
- 互換性
- 実行時間
- コマンド実行

v5とv6双方の環境用意するのが面倒くさかったので以下シナリオを分けてGitLab Runnerで環境準備しています。

- `molecule/default`がv5用のシナリオ
- `molecule/default6`がv6用のシナリオ

### レポジトリ

https://gitlab.com/miyuk/role_molecule_test

### GitLab Runnerの実行結果

https://gitlab.com/miyuk/role_molecule_test/-/pipelines/967761446


## コンフィグ差分

バージョン変更したことにより変わった部分は以下の通り。

### molecule.yml

Moleculeがpodmanでコンテナを作る際に`containers.podman`コレクションを使って構築しています。

v5ではプラグイン側で自動的にAnsibleコレクションをダウンロードしてくれていましたが、
v6では明示的にダウンロードする必要があるので`dependency.options.requirements-file`に`requirements.yml`を指定します。

`driver`はデフォルトでdefaultになったので省略しています。

`platforms[*].pre_build_image`は、`false`にすることでインスタンスがAnsible実行できるようにMoleculeがローカルコンテナイメージ作成してくれるオプションです。
v6ではそもそも対応しておらず、不要なので削除しています。

```diff_yaml:molecue.yml
dependency:
  name: galaxy
+  options:
+    requirements-file: requirements.yml
-driver:
-  name: podman
platforms:
  - name: instance or instance6
    image: quay.io/centos/centos:stream8
-    pre_build_image: true
provisioner:
  name: ansible
verifier:
  name: ansible
```

### requirements.yml

Moleculeがpodmanを操作するために、`containers.podman`を記載します。
dockerを使う場合は、ここが`community.docker`になります。

```yaml:requirements.yml
collections:
  - containers.podman
```

### create.yml, destroy.yml

v5はmoleculeを走らせるとプラグインが勝手にテスト用コンテナを構築・削除してくれましたが、
v6では開発者がAnsibleで構築・削除する必要があります。

こちらは、公式にサンプルとして用意されているものをそのまま使っています。
詳細は以下URLの通り。

https://github.com/ansible/molecule/blob/main/molecule/podman/create.yml

https://github.com/ansible/molecule/blob/main/molecule/podman/destroy.yml

## 互換性

2023/8/15時点で以下確認しました。

1. v6でv5用シナリオ(podmanドライバ利用)がテストできるか
2. v5でv6用シナリオ(defaultドライバ利用)がテストできるか

`1. v6でv5用シナリオ(podmanドライバ利用)がテストできるか`は、現時点で問題なく実行可能でした。
しかし、冒頭でも言った通り一時的にサポートしない状態となっているのでどこかのタイミングで利用できない可能性は大いにあります。
利用する際は注意が必要そうです。

`2. v5でv6用シナリオ(defaultドライバ利用)がテストできるか`は、`dependency`で以下WARNINGが出て`requirements.yml`を読み込んでくれない問題点がありました。
事前にコレクションをインストールするか、molecule.ymlで`collections-path`を代わりに使ってあげることで対応可能です。

コレクションがきちんと入っていれば、問題なく実行できるようでした。

```
Molecule default6 > dependency
[WARNING]: The requirements file
'/builds/miyuk/role_molecule_test/molecule/default6/requirements.yml' contains
collections which will be ignored. To install these collections run 'ansible-
galaxy collection install -r' or to install both at the same time run 'ansible-
galaxy install -r' without a custom install path.
Skipping install, no requirements found
INFO     Dependency completed successfully.
WARNING  Skipping, missing the requirements file.
```

## 実行時間

時間についてv5用シナリオとv6シナリオを比較しました。
v6シナリオのほうが`create`で若干速い結果となりました。

v5シナリオでも内部的にはAnsibleで同じコレクションを利用しているので、おそらくv5の方は他オプションも対応している部分がオーバヘッドになっている可能性があります。
ただし、ほとんど変わらないので気にするほどではなさそうです。

|工程|v5 podman|v6 podman|v5 default|v6 default|
|----|----|----|----|----|
|dependency|0|0|0|2|
|cleanup|0|0|0|0|
|destroy|12|11|11|12|
|syntax|0|0|0|1|
|create|13|13|8|7|
|prepare|0|0|0|0|
|converge|3|3|3|3|
|idempotence|3|3|3|3|
|side_effect|0|0|0|0|
|verify|3|2|3|3|
|cleanup|0|0|0|0|
|destroy|12|11|11|12|
|**合計(秒)**|**46**|**43**|**39**|**43**|

## コマンド実行

各コマンドを使ってみましたが、v6では`molecule login`が対応できていませんでした。

`default`ドライバで別ホストを使う場合、開発者側でインスタンス情報を`instance_config.yml`に保存してそれを使ってSSHログインしに行くようです。

https://github.com/ansible/molecule/blob/main/molecule/default/create.yml

しかし、コンテナの場合は`podman` or `docker`コマンドでログインするためそのままでは実装できないようでした。

~~`podman exec`コマンドで代用はできますが、`molecule login`はよく使うのでここは大きなマイナスポイントと感じました。
一応、molecule.ymlで`login_cmd_template`を使うと解決しそうなのでそちらは今後試してみたいと思います。~~

以下をmolecule.ymlに追記することで`molecule login`対応できました。

```yaml
driver:
  options:
    managed: false
    login_cmd_template: >-
      podman exec
      -e COLUMNS={columns}
      -e LINES={lines}
      -e SHELL=bash
      -e TERM=xterm
      -ti {instance} bash
```
# 感想

Molecule v6になってユーザ側が管理すべきファイルが増えましたが、
pluginでブラックボックス化していてものを明示的に宣言できるという意味では分かりやすくなったと思います。

サポートが一時的に止まっていとはいえ、まだ外部ドライバーは今のところ使えそうで互換性は担保できそうです。

シンプルな構成であれば設定変更差分も少ないため、一旦検証すればアップデート対応も苦ではなさそう。

[コミュニティでの議論](https://github.com/ansible/molecule/issues/3919)としても以下を目的としており、まだ道半ばだと思うので気長に開発を見守っていきたいと思います。

- グルーコードをなくしてAnsible Playbook開発者がMoleculeテストの成約を下げる
- Ansibleコレクションと連携させる
- 複数の方法、複雑な条件でインスタンスを作成できる

# 参考URL

https://github.com/ansible/molecule

https://ansible.readthedocs.io/projects/molecule/

https://github.com/ansible-community/molecule-plugins

https://github.com/ansible/molecule/issues/3919