Ansible Lint と yamllint の話 (イントロダクション)
What's this?
これは次の Ansible Advent Calendar 2020 に参加して書いている記事となります。 他の方の記事については下記のリンクからたどれますので是非あわせてご参照下さい。
Lint って何?
Lint って何でしょう? Wikipedia に丁度、lint の記事 https://ja.wikipedia.org/wiki/Lint があるようなので見てみましょう。
lint とは、主にC言語のソースコードに対し、コンパイラよりも詳細かつ厳密なチェックを行うプログラムである。静的解析ツールとも呼ばれる。 (中略) コンパイラではチェックされないが、バグの原因になるような曖昧な記述についても警告される。 構文(シンタックス)レベルのチェックだけでなく、意味(セマンティクス)レベルのチェックまで実行するものもある。
ソースコードの静的解析とはソースコードをコンパイル、実行することなく読込み、何らかの解析を行なってチェックすることです。 Ansible と C 言語などプログラム言語のソースコード、どう関係するのだろう? と思われる方もいらっしゃるかもしれませんが、 Ansible Playbook の YAML ファイルも IaC [1] 化された『(ソース) コード』と見做すことができますし、 プログラミング言語の場合と同様に静的解析して同じようなことができそうということは想像できるかと思います。
実際に Ansible Playbook の YAML ファイルを静的解析、チェックするためにいくつか OSS のツールが開発されていてすぐに使うことができます。 Ansible の Lint ツールとして有名な二つについて次の節では簡単に紹介しておきます。
[1] | IaC = Infrastructure As Code、詳しくは https://ja.wikipedia.org/wiki/Infrastructure_as_Code などをご参照下さい。 |
Ansible で使える Lint ツール
Ansible Lint
Ansible Lint は Ansible Playbook などを対象に静的解析を行ない、経験則などに基づいてより良い書き方がなされているかをチェックすることができます。 標準でも最低限必要十分と思われるチェックが可能ですが拡張してチェック項目を増やすこともできます。
- プロジェクト: https://github.com/ansible/ansible-lint
- ドキュメント: https://ansible-lint.readthedocs.io
- コマンド行のツール: ansible-lint
- Ansible Playbook・Role を構成するいくつかの YAML ファイルなどを対象に静的解析を実行
- 静的解析でチェックする項目は Rule としてまとまっている
- Rule 毎に設定で有効化・無効化の指定が可能
- 構文チェックより一歩踏み込んで Playbook や Task 定義などの書き方をチェック可能
- 標準の Rule 集: https://ansible-lint.readthedocs.io/en/latest/default_rules.html
- カスタム Rule 実装 (Python コード) を用意すれば拡張できる: https://ansible-lint.readthedocs.io/en/latest/rules.html#creating-custom-rules
yamllint
yamllint は YAML ファイルを対象に静的解析を行ない、経験則などに基づいてより正しく、良い書き方がなされているかをチェックすることができます。 Ansible に特化したものではないですが Ansible Playbook や Role を構成する大部分のファイルは YAML ファイルなので活用できます。
- プロジェクト: https://github.com/adrienverge/yamllint
- ドキュメント: https://yamllint.readthedocs.io
- コマンド行のツール: yamllint
- YAML ファイルを対象に静的解析を実行
- 静的解析でチェックする項目は Rule としてまとまっている
- Rule 毎に設定で有効化・無効化や用意されていれば細かなオプション指定による調整が可能
- 構文チェックはもちろん一歩踏み込んで経験則などに基づいて書き方をチェック可能
- 標準の Rule 集: https://yamllint.readthedocs.io/en/latest/rules.html
なお yamllint についてはカスタム Rule 実装 (Python コード) を用意してすぐ拡張できるような仕組みは upstream では用意されていませんが、筆者が開発作業中の branch を使えば plugin により拡張可能です。
- 筆者が開発作業中の yamllint を pluing で拡張可能にできる branch: https://github.com/ssato/yamllint/tree/feature/plugin
- upstream に対する Github PR: https://github.com/adrienverge/yamllint/pull/315
なぜ Lint が必要?
Ansible Playbook でも Lint ツールがあって色々静的解析できそうということはわかりました。 ではなぜこれらの Lint ツールが必要で、何が嬉しいのでしょうか?
筆者は主に次のようなメリットがあると考え、積極的に Lint ツールの利用をすすめています。 (利用はほぼ必須と考えています。)
- Ansible Playbook を実行せずに簡単に構文の間違い、ケアレスミスなどをみつけることができる
- Ansible Playbook を実行せずに簡単により良い Playbook の書き方を教えてもらえる
- Ansible Playbook を実行せずに簡単に Playbook を確認できて、人によらず一定品質を保つ手助けとできる
- CI ワークフローの中に簡単に組み込むことができる
例えば Ansible Playbook の中で同じことを行う task であっても色々な書き方で定義することができます。 これ自体は良いことではあるのですが Playbook を複数人で開発、利用していこうとすると非常に問題となります。
例えば httpd を RPM パッケージでインストールする task 定義を書く場合でも色々考えられます [2] 。
shell モジュールを利用 (1):
- shell: yum install -y httpd
shell モジュールを利用 (2):
- name: Ensure httpd package is installed shell: yum install -y httpd
command モジュールを利用:
- name: Ensure httpd package is installed command: yum install -y httpd
package モジュールを利用 (1):
- name: Ensure httpd package is installed package: name=httpd state=present
package モジュールを利用 (2):
- name: Ensure httpd package is installed package: name: httpd state: present
package モジュールを利用 (3):
- name: Ensure httpd package is installed package: name: - httpd state: present
yum モジュールを利用:
- name: Ensure httpd package is installed yum: name: - httpd state: present
人によって書き方がばらばらだと保守が大変になりますし、すべてのパターンについてきちんとテストする工数も増大します。 Lint ツールによってより良い書き方となっているかをチェックし、ある程度標準化された書き方にそろえていくことで Playbook の品質を上げ、開発保守をより安全に進めることができるようになるわけです。
[2] | もし余裕があれば、この例の中でどの書き方が一番良いか、またそれはなぜかを考えてみて下さい。 |
次回予告
次回以降では実際に Ansible Lint と yamllint をどう使っていくのか実例を示しながら簡単に紹介する予定です。