AnsibleでMacの開発環境を整える際にぶち当たった問題。
vagrant plugin install
は既にインストールされていてもそのまま強制的に上書きインストールを始めてしまう。
シェルスクリプトでBrewfile的なものを書いていた時は簡単にインストールをスキップする処理を書けたが、ansibleで同じことを実現するのにやや詰まったのでメモ。
いままで
今までは以下のようにしていたから少し気持ち悪かった。
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: Install Vagrant Plugins
shell: "vagrant plugin list | grep {{item}} || vagrant plugin install {{item}}"
with_items:
- vagrant-omnibus
- vagrant-vbguest
- vagrant-cachier
- vagrant-vbox-snapshot
- vagrant-aws
- vagrant-digitalocean
これだと、以下のようにitem全てについてchangedが出てしまう。しかもループごとに毎回vagrant plugin list
を実行するので遅い。
見つけた解
一つのスマートな解として以下の様なものに落ち着いた。
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: List Installed Vagrant Plugins
shell: "vagrant plugin list | awk '{ print $1 }'"
changed_when: false
register: vagrant_plugin_list
- name: Install Vagrant Plugins
shell: "vagrant plugin install {{item}}"
with_items:
- vagrant-omnibus
- vagrant-vbguest
- vagrant-cachier
- vagrant-vbox-snapshot
- vagrant-aws
- vagrant-digitalocean
when: item not in vagrant_plugin_list.stdout_lines
出力は以下。
ASK: [List Installed Vagrant Plugins] ****************************************
ok: [localhost]
TASK: [Install Vagrant Plugins] ***********************************************
skipping: [localhost] => (item=vagrant-omnibus)
skipping: [localhost] => (item=vagrant-vbguest)
skipping: [localhost] => (item=vagrant-cachier)
skipping: [localhost] => (item=vagrant-vbox-snapshot)
skipping: [localhost] => (item=vagrant-aws)
skipping: [localhost] => (item=vagrant-digitalocean)
1つ目のtaskでvagrant plugin list
の出力をregisterしておく。awkで一つ目のフィールド(プラグイン名のみ)を取り出す。
2つ目のtaksでループ。ただし1つ目のタスクの出力で出ていないもののみ実行。
ポイントはstdout_lines
でした。grep
芸で実行するよりもスマートで、シェルシェルしないAnsibleらしいものになったかなと。
ただskipping
よりok
のほうが気持ちがいい・・・。ok
にする方法は今後思いついたら書く。