notebook

都内でWEB系エンジニアやってます。

ansibleメモ(サンプル集)

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 }}

{{ 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が適用されるのでこの場合のインストール条件は

  • zshコマンドが存在しない
  • zshのバージョンが指定したバージョンではない

のどちらかの場合にインストール処理が走る

環境変数の追加

上述の/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(デバッガ)

github.com

これは便利、fialした段階で変数の中身などをのぞいたり上書きして動作させてみることが出来るのでplaybookを書くのが捗る

READMEにも書いてますがstrategy_plugins/にソースを置いて下記記述するだけ

  • site.yml
strategy: debug

一つ気になったのは ignore_errors: true でもデバッガが起動してしまうこと...

おわり

冪等性を保つために色々試してみたけど難しいですね

今回2系での新らしい構文とかはあまり使わなかったので今度使ってみようと思います