zaki work log

作業ログやら生活ログやらなんやら

[Ansible] roleの雛形作成をカスタムする (ansible-galaxy / --role-skeleton)

roleの雛形の作り方と、雛形のカスタマイズ。
今回は試さなかったけどcollectionにも使えるはず。。

role雛形の作成

Ansibleのroleの雛形は、ansible-galaxyを使って以下のコマンドで作成できます。

$ ansible-galaxy init my-role
$ tree my-role/
my-role/
├── README.md
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

8 directories, 8 files

引数で指定した「my-role」というrole名で各ファイルが生成され、各ファイル内のrole名がセットされます。

role雛形のカスタム

role作成のansible-galaxyのオプションで--role-skeleton=/path/to/role-skeletonを指定することで、雛形のスケルトン(ややこしい)を指定できます。
ケルトンは一旦ansible-galaxy initでrole雛形を作り、出来た雛形に必要なファイルを作成・編集したり、不要ファイル削除したりすれば、それをスケルトンとして使用可能。
例えば「ディレクトリだけのfilestemplatesは要らん(必要があるときに作る)」「defaultsは使わない」「README.mdはプロジェクトのテンプレートを使う」とか。

雛形のスケルトンを作る

$ ansible-galaxy init role-skeleton
- Role role-skeleton was created successfully

そこから(例として)不要なファイルを削除。

$ rm -rf role-skeleton/files/ role-skeleton/handlers/ role-skeleton/templates/ role-skeleton/defaults/
$ tree role-skeleton/role-skeleton/
├── README.md
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

4 directories, 6 files

(例として)READMEを編集。(ちなみにREADME.md.orgは残しておくとこれも雛形に含まれるので削除を忘れずに)

$ diff -u role-skeleton/README.md.org role-skeleton/README.md
--- role-skeleton/README.md.org 2021-08-27 08:39:54.140736835 +0900
+++ role-skeleton/README.md     2021-08-27 08:43:23.359197543 +0900
@@ -1,38 +1,34 @@
 Role Name
 =========
 
-A brief description of the role goes here.
+fixme
 
 Requirements
 ------------
 
(中略)

 License
 -------
 
-BSD
+MIT
 
 Author Information
 ------------------
 
-An optional section for the role authors to include contact information, or a website (HTML is not allowed).
+@zaki_hmkc

ケルトンからroleの雛形を作成

↑で作成したスケルトンを指定してrole雛形を作成します。

$ ansible-galaxy init --role-skeleton=./role-skeleton customize-role
- Role customize-role was created successfully

これでカスタムしたスケルトンで用意したファイルのみのrole雛形になります。

$ tree customize-role/
customize-role/
├── README.md
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

4 directories, 6 files

カスタムしたREADME.mdもこの通り。

$ cat customize-role/README.md 
Role Name
=========

fixme

Requirements

(中略)

License
-------

MIT

Author Information
------------------

@zaki_hmkc

role名の埋め込み

ただし↑の手順だけだと、ファイル内のrole名がセットされる箇所が、スケルトンを作ったときのままになります。

$ cat customize-role/tasks/main.yml 
---
# tasks file for role-skeleton

ここにスケルトンではなく新しく作るrole雛形の名前をセットするにはJinja2テンプレートで変数を指定します。
その際、テンプレートで変数使う場合はファイル名も.j2を追加します。

tasks/main.ymlでテンプレートを参照するのであれば、tasks/main.yml.j2にして、role名に置き換えたい箇所を{{ role_name }}に置き換えます。

$ cat role-skeleton/tasks/main.yml.j2
---
# tasks file for {{ role_name }}

この内容のスケルトンを指定してrole雛形を作成すると、以下の通り。

$ ansible-galaxy init --role-skeleton=./role-skeleton customize-role2
- Role customize-role2 was created successfully
$ cat customize-role2/tasks/main.yml 
---
# tasks file for customize-role2

role名を変換できました。
現状変数指定できるのは{{ role_name }}のみ、とのこと。
また、templatesディレクトリ以下の*.j2ファイルに対しては、テンプレートとしての変数変換は行われません。(なので、スケルトンに用意したファイルはそのまま雛形として出力される)

any .j2 files found outside of a templates folder will be rendered as templates. The only useful variable at the moment is role_name

https://docs.ansible.com/ansible/latest/galaxy/dev_guide.html#using-a-custom-role-skeleton

role名変換とJinja2テンプレートの書式を同時に使いたいとき

ファイル名を.j2にすると、ファイル内のJinja2テンプレートの変数参照は全て雛形作成時に変換処理が行われます(そして{{ role_name }}以外は未定義エラーになる)。

{{ role_name }}は変換しつつ、それ以外はJinja2として解釈せずにそのまま雛形作成するには、Jinja2の{% raw %}を使ってエスケープします。

タスクのスケルトンをこのように記述しておくと、

$ cat role-skeleton/tasks/main.yml.j2
---
# tasks file for {{ role_name }}
- name: print values
  ansible.builtin.debug:
    msg: {% raw %}"{{ role_values }}"{% endraw %}

生成されるrole雛形のタスクファイルはこの通り。
{{ role_name }}はテンプレートとして変換されて、{{ role_values }}はそのまま。

$ cat customize-role3/tasks/main.yml 
---
# tasks file for customize-role3
- name: print values
  ansible.builtin.debug:
    msg: "{{ role_values }}"

↑は変数参照部分だけ'{% raw %}`で囲んでるけど、個数が多いなら上から下まで丸ごと囲んでも良いかも。

参考情報

docs.ansible.com

「Using a custom role skeleton」参照。

環境

ansible-galaxy [core 2.11.2] 
  config file = /home/zaki/.ansible.cfg
  configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/zaki/src/ansible-sample/venv/ansible4/lib64/python3.6/site-packages/ansible
  ansible collection location = /home/zaki/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/zaki/src/ansible-sample/venv/ansible4/bin/ansible-galaxy
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
  jinja version = 3.0.1
  libyaml = True

Pythonのバージョンが(ry