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系での新らしい構文とかはあまり使わなかったので今度使ってみようと思います