の投稿です。
まだGoもAnsibleも良くわかってない頃に作った、Goの環境を整えるAnsibleの設定をリファクタリングしました。
やってる事はごく当たり前なんですが、冪等性を担保し、changedが出ないことによって何回でもいつでも実行できる環境にしたので、その過程をメモします。
リファクタリング前と リファクタリング後はそれぞれリンクをご参照下さい
Goのバージョンが1.4で古かったので1.5に上げました。
ちなみに1.4と1.5はこんな感じに違うそうです。
URL内にバージョン番号をハードコードしていたのでvarsの中に移して、バージョン番号の変更漏れを起こさないようにしました。(差分)
以後はURLに変更がなければこのように変えるだけで良くなりました。
shell, commandモジュールはシェルなので便利ですが、代わりに全ての操作がchanged
になってしまいます。
これでは プロビジョニングを実行した結果何が変わったのか が分かりません。安心感に欠けます。
幸い、それらのモジュールを使わないで済む代替手段が色々あったので、なるべくそちらに寄せていきます。 ファイルの上書きなどで冪等性をシェルだけで担保しようとするとかなり煩雑になってしまうので、とても有り難いです。
以下に何かと使いそうな例と、それを利用したリファクタの差分を出してみました。
それでもやっぱり、シェルにお力添え頂きたい箇所は出てしまいます。
そんなときはchanged_when
というプロパティを足して、実行した結果何か変わったのか否か? を明示してあげると、シェル系のモジュールを使用してもokが出るようになります。
例えばGoのバージョンチェックでは標準出力の内容に指定した文字列が含まれるか否かでchangedを出しています。
- name: check Go version
shell: go version | awk '{ print $3 }'
register: go_version
ignore_errors: yes
changed_when: "go_version.stdout.find('go{{ goversion }}')"
例えばgodep saveでは、終了コードも標準出力の内容も違わないため無理かと思いましたが、ゴリ推しました。
godep save実行後にGodeps/Godeps.json
のdiffを見てもし差分が出ていればchangedという判定にしました。
- name: save go dependencies
shell: cd {{ apppath }} && go get && godep save && git diff Godeps/Godeps.json
register: godep_diff
changed_when: "godep_diff.stdout != ''"
実行結果のgifアニメを撮ってみました。
二回目の実行では全部okになります。
これで(シェルがバグってなければ)冪等性が担保できるようになりました。
今回の場合は開発環境の初期構築しかやってないので最初の一回しか実行する必要無いんですが、冪等性のある設定がきちんと書けるようになっていると必要なときに何かと役立つと思います。
まだまだAnsibleの知識と慣れが不足しているので、よりよい書き方などご教授頂けると幸いです。