今年Ansibleでよく使ったモジュールと仕様方法について

# 今年Ansibleでよく使ったモジュール
Ansibleに初めて触れたのは今年の4月なので計7ヶ月程度ではありますが、その中でよく使ったモジュールとどのように使ったかを書いていこうと思います。使い初めの頃、モジュールの意味はわかっても`どう使えば良いか？`に迷ったことがよくあったのでそういう人の参考になればと思います。


## 紹介モジュール一覧
* when
* block
* yum
* shell
* ignore_errors
* with_items
* include_tasks
* assert
* systemd
* ansible_facts(distribution)
* debug
* register

### when
条件文で使用します。
`直前のタスクの実行結果が成功だったら`、`OSがLinuxの7系だったら`、などの条件を指定して合致した時だけタスクを実行させたいなどの時に使えます。

```yaml
[playbook]
- hosts: vagrants
  tasks:

  - name: when-7
    shell: echo "linux7系です。"
    when: ansible_distribution_major_version == "7"

  - name: when-6
    shell: echo "linux6系です。"
    when: ansible_distribution_major_version == "6"

[実行結果]
PLAY [vagrants] ******************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************
ok: [192.168.11.10]

TASK [when-7] ********************************************************************************************************************************************************************************************
changed: [192.168.11.10]

TASK [when-6] ********************************************************************************************************************************************************************************************
skipping: [192.168.11.10]

PLAY RECAP ***********************************************************************************************************************************************************************************************
192.168.11.10              : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
```
二つのタスクを実行して一つは実行され、一つはスキップされています。
when条件で`ディストリビューションのメジャーバージョンが6の場合、7の場合`でそれぞれタスクを用意しました。
対象環境がCentos7なので`when-7`のタスクだけが実施されました。


### block
複数のタスクを一つの固まりにしてくれます。
whenと組み合わせると便利です。一つ一つのタスクにwhenを記載するのは面倒ですが、blockを使えばblockに対してだけwhenを指定すれば判定は一回で済みます。

```yaml
- hosts: vagrants
  tasks:

  block:
    - name: when-7-標準語
      shell: echo "linux7系です。"

    - name: when-7-関西弁
      shell: echo "linux7系やで。"

  when: ansible_distribution_major_version == "7"
```
こんな感じで記載すれば、`メジャーバージョンが7系であれば上記二つのタスクを実施してくれます。`
ちなみにさっきから例で記載してるshellモジュールのタスク内容に意味は全くないです。


### yum
yumパッケージのインストール、アンインストールで使っていました。
モジュールのパッケージ（コマンドで言うところのオプションみたいなもの）で切り替えます。インストールされているかの確認でも使っていましたが、listを使うと対象サーバに入ってるかでなくリポジトリにあるかを見るので欲しい情報と微妙に違ってたり。。リストの値を絞れば一応インストールされているものだけ選別することも可能です。

下記は複数インストールする時を例にしてます。

```yaml
- hosts: vagrants
  tasks:

  block:
    - name: install
      yum:
        name:
          - httpd
          - git
```
nameに紐付けすれば複数インストール出来ます。こういうのはshell使って書くより見やすいですね。


### shell
普通のコマンドが使いたい！と言う時に使用するモジュールです。
shellモジュールで指定したコマンドを実行します。ただ、普通のコマンドを使うことになるので、あんまり使わない方が良いです。Ansibleがやってくれてる冪等性がそのタスクだけ損なわれてしまいます。`普通のコマンドが使いたいならスクリプトシェル作った方が楽です。`


### ignore_errors
タスクで使用すれば、その処理内容がエラーだったとしても処理を終了せずに次のタスクを実施します。
`shellモジュールで確認を行なっているが、エラーであることを確認したい（例えばファイルに対象の文字が無いとか）`なんて時に使えます。

```yaml
- hosts: vagrants
  tasks:

  - name: test
    shell: cat /tmp/test | grep error
```
`/tmp/test`内にエラーが無いか確認してます。ファイル内にerrorが無いと、failedで失敗します。

```yaml
[実行結果]
PLAY [vagrants] ******************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************
ok: [192.168.11.10]

TASK [test] **********************************************************************************************************************************************************************************************
fatal: [192.168.11.10]: FAILED! => {"changed": true, "cmd": "cat /tmp/test | grep error", "delta": "0:00:00.007188", "end": "2019-12-18 14:38:52.086180", "msg": "non-zero return code", "rc": 1, "start": "2019-12-18 14:38:52.078992", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}

PLAY RECAP ***********************************************************************************************************************************************************************************************
192.168.11.10              : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

```

ただ、今回は無くてOK（エラーで良い）なのでエラーが出ても処理を継続して欲しいとします。

```yaml
[playbook]


[実行結果]
TASK [Gathering Facts] ***********************************************************************************************************************************************************************************
ok: [192.168.11.10]

TASK [test] **********************************************************************************************************************************************************************************************
fatal: [192.168.11.10]: FAILED! => {"changed": true, "cmd": "cat /tmp/test | grep error", "delta": "0:00:00.003701", "end": "2019-12-18 14:46:42.121659", "msg": "non-zero return code", "rc": 1, "start": "2019-12-18 14:46:42.117958", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

PLAY RECAP ***********************************************************************************************************************************************************************************************
192.168.11.10              : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1
```

failedが0になってignoredが1になっています。これでここのタスクがfailedだったとしても無視して次のタスクに進みます。このタスクに関してはもっとスマートにできる気がしないでも無いですが、一例ということで。

### with_items
処理をループさせる時に使用します。
複数のファイル・フォルダを用意したい時に、それぞれタスクを用意せずにループ処理でスッキリさせることが出来ます。
with_itemsのリストの値を使用する時は`{{ item }}`で呼び出せます。

```yaml
- hosts: vagrants
  tasks:

  - name: test
    file:
      path: "/tmp/{{ item }}"
      state: directory
    with_items:
      - test1
      - test2
```

/tmp配下にtest1とtest2というフォルダを作成しました。
下記はサーバ内で実際に作ったフォルダを確認してます。

```shell
$ ls /tmp/
test  test1  test2
```

### include_tasks
ここで指定したファイルを読み込んで処理を行います。
`OSバージョンによって処理内容が大きく変わるなどの時に、処理ごとに読み込ませるファイルを変えれば管理が楽になります。`


```yaml
- name: タスク読み込み
  include_tasks: example6.yaml
  when: ansible_distribution_major_version == "6"


- name: タスク読み込み
  include_tasks: example7.yaml
  when: ansible_distribution_major_version == "7"
```

この例だと、6系だとexample6.yamlを読み込み、7系だとexample7.yamlを読み込みます。

### assert
`条件に合致すれば何もせず、逆に合致しなければ指定したメッセージを流して処理を終了する。と言う使い方が出来ます。`

```yaml
- hosts: vagrants
  tasks:

  - name: test
    file:
      path: "/tmp/{{ item }}"
      state: directory
    with_items:
      - test1
      - test2

  - name: file count
    shell: ls /tmp/ | wc -l
    register: file_check

  - name: file check
    assert:
      that: "{{ file_check.stdout == '2' }}"
      msg: "想定よりファイル数が多いです。確認してください。"
```

`/tmp/配下のファイル数が作成した数より多ければmsgに書いた内容を出力する`という内容で書いてます。
実行結果も貼ります。/tmp環境のファイル数を2より多くしてるのでエラーメッセージが出ます。

```yaml

[実行結果]
PLAY [vagrants] ******************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************
ok: [192.168.11.10]

TASK [test] **********************************************************************************************************************************************************************************************
ok: [192.168.11.10] => (item=test1)
ok: [192.168.11.10] => (item=test2)

TASK [file count] ****************************************************************************************************************************************************************************************
changed: [192.168.11.10]

TASK [file check] ****************************************************************************************************************************************************************************************
fatal: [192.168.11.10]: FAILED! => {
    "assertion": false,
    "changed": false,
    "evaluated_to": false,
    "msg": "想定よりファイル数が多いです。確認してください。"
}

PLAY RECAP ***********************************************************************************************************************************************************************************************
192.168.11.10              : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

```

### systemd
サービスの起動、停止、自動起動のオンオフに使用していました。
これは特別変わった使い方はしてないので例は特に書きません。

公式で実施例があってそれを見るだけでなんと無くわかると思うのでそのURLだけ貼っておきます。
https://docs.ansible.com/ansible/latest/modules/systemd_module.html


### ansible_facts
ansibleが自動で定義している変数を指します。
私はもっぱら`OSのディストリビューションやOSのメジャーバージョンの取得に使っていました。`
Linuxの6系か7系かでファイルの格納場所が違ったりするので何気によく使います。

上のタスクの実行例でちょいちょい使ってたやつですね。これ以外にもディストリビューション（CentOSかRHELか等）の情報も取得出来ます。
他にもAnsibleは大量の情報を取得してるので興味があれば書きタスクを実行してみると、どんな情報を取得してるかわかります。ちょっと量が多いのでここでは貼りません。（というか、なんか重要そうな情報も入ってそうだったので。。）

```yaml
- hosts: vagrants
  tasks:

  - name: facts
    debug:      
      msg: "{{ ansible_facts }}"  
```

### debug
検証で最もよく使ったモジュールです。
`実行結果を条件で指定したけどなんか処理がおかしい時に、実験結果の変数に何が入っているか`を確認するのに使用していました。
使い方は上のタスクで使ってるのを参考にしてもらえれば。。

### register
debugと併せてよく使っていたモジュール。
`実行結果の様々な情報を指定の変数に詰めてくれます。`
registerで結果を取得して、assertでメッセージを出したりwhenで条件分岐したりの合わせ技で使っていました。


## 終わりに
大した数じゃ無いと思ってましたが、いざ文字に起こすと結構難しいですね。。
`こんな使い方そうしねぇよ、もっと実用的な例にしろよ！`ってのがあるとは思いますが、ちょっと良い例が思いつかなくて。。もっと他の使い方を知りたいとかあればコメントください。出来るだけ盛り込みます。