ansible2.1を触ってみたのでそのメモ
開発環境の構築をansibleで出来るようにplaybookを書いたのでそのときにメモしたものです
といいつつ2.1の変更点というよりは1系でも書けるもののほうが多いです
factのリスト
$ ansible -i hosts hostrole -m setup 192.168.30.93 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "172.18.0.1", "172.17.0.1", "10.0.2.15", "192.168.30.93" ], "ansible_all_ipv6_addresses": [ "fe80::42:a8ff:fe29:3b30", "fe80::42:4bff:fea9:2bfa", "fe80::a00:27ff:fef6:b007", "fe80::a00:27ff:fe7c:28bd", "fe80::3807:a4ff:fe85:3ce", "fe80::4cfd:96ff:fe9e:c88b", "fe80::9853:ceff:fe45:ed05", "fe80::e8b7:64ff:fe89:3b1d", "fe80::f00f:4aff:fee8:1e63" ], "ansible_architecture": "x86_64", "ansible_bios_date": "12/01/2006", "ansible_bios_version": "VirtualBox", "ansible_br_c613bbde3920": { ..... .....
ここで得られるもの一部抜粋
{{ ansible_architecture }}
- システム(Linux)
{{ ansible_system }}
hashのマージ
vars_filesや各タスクのvarsファイルで変数が被ったときに変数をマージする
[defaults] hash_behaviour=merge
vars_file等の定義を優先させる
- vars_files
zsh_v: 5.2
- roles/.../vars/main.yml
zsh_version: "{{ zsh_v|default('5.1')}}"
5.2がインストールされる
と色々やってみたけど roles/defaults/main.yml
に書けば優先順位もうまくクリアできるのでそっちのほうがいいですね
- vars_files
zsh_version: 5.2
- roles/.../defaults/main.yml
zsh_version: 5.1
この場合も5.2がインストールされる、こっちのほうがスマート
色々な事情でデフォルトを定義したいときとかには使える...はず
./configure make make install の流れ
よくあるやつ
2系からblock構文が使えるようになったので取り入れてみました
- block: - name: get source get_url: url: "{{ zsh.src }}" dest: /tmp/{{ zsh.tgz }} - name: unarchive tar.gz unarchive: src: /tmp/{{ zsh.tgz }} dest: /tmp copy: no - name: configure make install command: chdir=/tmp/{{ zsh.dir }} {{ item }} with_items: - ./configure - make - make install
コマンド存在チェック
コマンドが無ければインストールする、などの場合に使う
environmentを入れてるのはなぜか/usr/local/bin
にパスが入っていないから...
- name: exist zsh command: which zsh environment: PATH: "/usr/local/bin:{{ ansible_env.PATH}}" register: exist_zsh changed_when: false ignore_errors: true
whichはコマンドが存在する場合はresult code(rc)が0、存在しない場合は1が返るのでそれを利用する
バージョンチェック
version_in_zshの中身によってインストール作業を行ったりできる
- name: get zsh version shell: zsh --version environment: PATH: "/usr/local/bin:{{ ansible_env.PATH}}" register: version_in_zsh changed_when: false ignore_errors: true when: exist_zsh.rc == 0
version_in_zsh.stdout.find(zsh_version)
取得した値から対象のバージョンが見つからない場合-1
が返る
見つかった場合見つかった位置が返る
バージョンが合わなければインストールする
上記二つを組み合わせたパターン
- name: exist zsh command: which zsh environment: PATH: "/usr/local/bin:{{ ansible_env.PATH}}" register: exist_zsh changed_when: false ignore_errors: true - name: get zsh version shell: zsh --version environment: PATH: "/usr/local/bin:{{ ansible_env.PATH}}" register: version_in_zsh changed_when: false ignore_errors: true when: exist_zsh.rc == 0 - block: - name: get source get_url: url: "{{ zsh.src }}" dest: /tmp/{{ zsh.tgz }} - name: unarchive tar.gz unarchive: src: /tmp/{{ zsh.tgz }} dest: /tmp copy: no - name: configure make install command: chdir=/tmp/{{ zsh.dir }} {{ item }} with_items: - ./configure - make - make install when: exist_zsh.rc != 0 or ( version_in_zsh is defined and version_in_zsh.stdout.find(zsh_version) == -1 )
blockで囲った処理get source
,unarchive tar.gz
,configure make install
に対してwhenが適用されるのでこの場合のインストール条件は
のどちらかの場合にインストール処理が走る
環境変数の追加
上述の/usr/local/bin
へのパスは下記で対応できるかと思ったが出来なかった
[defaults] executable = /bin/bash -l
仕方なく必要なタスクに下記追加
environment: PATH: "/usr/local/bin:{{ ansible_env.PATH}}"
デバッグ
- スペースが存在する場合はダブルクォーテーションで囲む
- debug: var="version_in_zsh is defined" - debug: var=version_in_zsh.stdout.find(zsh_version) - debug: var=zsh_version - debug: var=version_in_zsh.stdout - debug: var="version_in_zsh is defined and version_in_zsh.stdout.find(zsh_version) == -1"
ハッシュに対しての繰り返し処理
ハッシュに対してチェックを行いその結果とあわせて処理するみたいなやつ
特定のバージョンが見つからなかった場合=インストールされていない場合はインストールする
- vars
envs: plenv: { version: 5.25.2 } rbenv: { version: 2.3.1 } pyenv: { version: 3.5.2 } ndenv: { version: v6.2.2 }
- tasks
with_togetherで複数の配列を渡すことが出来る
grepで引っかかる場合はresult codeが0で返ってくる、引っかからない場合はエラーのresult codeが返るのでそれを利用する
with_itemsのときに出来た item.key, item.valueといった使い方はwith_togetherでは出来ない
だが、ハッシュのキー(item.0)は取得できるので添え字として渡すことでvalueを取得する
- name: "exist version in every envs" shell: "{{ item.key }} versions | grep {{ item.value.version }}" register: exist_version changed_when: false ignore_errors: true with_dict: "{{ envs }}" - name: "install envs version" command: "{{ item.0 }} install {{ envs[item.0].version }}" when: item.1.rc != 0 with_together: - "{{ envs }}" - "{{ exist_version.results }}"
変数に手を加える
変数を展開するときにpythonの関数を使える
templatesだけかと思ったがtasksなどでも使える模様
例としてpythonのバージョンに対して複数のバージョン表記を出力する
vars: python_version: 3.5.2 tasks: - command: "echo {{ python_version }}" register: full_version - debug: var=full_version.stdout - command: "echo {{ python_version.rsplit('.',1).pop(0) }}" register: minor_version - debug: var=minor_version.stdout - command: "echo {{ python_version.split('.',1).pop(0) }}" register: major_version - debug: var=major_version.stdout
- 出力
TASK [debug] ******************************************************************* ok: [192.168.30.94] => { "full_version.stdout": "3.5.2" } TASK [debug] ******************************************************************* ok: [192.168.30.94] => { "minor_version.stdout": "3.5" } TASK [debug] ******************************************************************* ok: [192.168.30.94] => { "major_version.stdout": "3" }
意味は同じだけど微妙に欲しい値が違うからvarsに複数書く、ということが減らせそう
他にもpythonで使えるメソッドが使える、template以外でも使えるので便利(公式参照)
多用すると可読性を悪くしそうだけどある程度なら使ってもよさそう
plugin(デバッガ)
これは便利、fialした段階で変数の中身などをのぞいたり上書きして動作させてみることが出来るのでplaybookを書くのが捗る
READMEにも書いてますがstrategy_plugins/
にソースを置いて下記記述するだけ
- site.yml
strategy: debug
一つ気になったのは ignore_errors: true
でもデバッガが起動してしまうこと...
おわり
冪等性を保つために色々試してみたけど難しいですね
今回2系での新らしい構文とかはあまり使わなかったので今度使ってみようと思います