ansible-lint によるチェック機能の確認

#  ansible-lint によるチェック機能
『Ansible構築・運用ガイドブック インフラ自動化のための現場のノウハウ』の4章で ansible-lint で Playbook のチェックが行えるとなっています。書籍では、ansible-lint を使って、実際にチェックするところまでを書いています。
個人的に、Playbook を修正し、挙動が変わるか確認したかったため、ここに記載します。

## 要約
 - ansible-lint は、推奨されている Playbook の書き方を提案する
 - ansible-lint は、構文のチェックはしない

## 修正前の Playbook と実行結果
修正前の Playbook と実行結果は以下の通りです。

```yaml:nginx_install.yml
---
- hosts: all
  vars:
    ansible_become: yes
    ansible_become_method: sudo
  tasks:
    - name: Install Nginx
      block:
        - yum:
            name: nginx
            state: latest
      rescue:
        - debug:
            msg: "Error!"
      always:
        - debug:
            msg: "Always run this section"
```

```:実行結果1
[vagrant@localhost chapter4]$ ansible-lint nginx_install.yml 
[403] Package installs should not use latest
nginx_install.yml:9
Task/Handler: yum state=latest name=nginx __file__=nginx_install.yml __line__=10

[502] All tasks should be named
nginx_install.yml:9
Task/Handler: yum state=latest name=nginx __file__=nginx_install.yml __line__=10
```
## 実行結果の意味
[ansible-lint の default rules](https://docs.ansible.com/ansible-lint/rules/default_rules.html) に詳細な意味が書いてます。

 - [403] Package installs should not use latest  
   Defalut Rules では、  
   <font color="red">Package installs should use state=present with or without a version</font>  
   となっており、 version の有無にかかわらず state=present を使うべきだと記載があります。  
   書籍では version を指定することが推奨されていると説明されていました。  
   　
 - [502] All tasks should be named  
   Defalut Rules では、    
   <font color="red">All tasks should have a distinct name for readability and for --start-at-task to work</font>  
   すべてのタスクは、読む込み可能かつ --start-at-task が機能するための、個別の名前を持つべきだと記載があります。  
   書籍では名前を指定されていないタスクがあり、修正すればよいと説明されてました。  

##  Playbook を修正する(1回目）
```yaml:nginx_install.yml
---
- hosts: all
  vars:
    ansible_become: yes
    ansible_become_method: sudo
  tasks:
  - name: Install Nginx
    block:
      - name: Install Nginx in block
        yum:
          name: nginx
          state: 1.16.1
    rescue:
      - debug:
          msg: "Error!"
    always:
      - debug:
          msg: "Always run this section"
```

```:実行結果2
[vagrant@localhost chapter4]$ ansible-lint nginx_install.yml 
[vagrant@localhost chapter4]$ ansible-playbook -i hosts nginx_install.yml --check

PLAY [all] *********************************************************************************

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

TASK [Install Nginx in block] **************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "value of state must be one of: absent, installed, latest, present, removed, got: 1.16.1"}

TASK [debug] *******************************************************************************
ok: [localhost] => {
    "msg": "Error!"
}

TASK [debug] *******************************************************************************
ok: [localhost] => {
    "msg": "Always run this section"
}

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

[vagrant@localhost chapter4]$ 
```

ansible-lint では問題ないとされていましたが、Dry Run では state の指定の仕方が違うと表示されました。
<font color="red">fatal: [localhost]: FAILED! => {"changed": false, "msg": "value of state must be one of: absent, installed, latest, present, removed, got: 1.16.1"}</font>
と、なっているため、 name: nginx-1.16.0, state: present を指定します。

##  Playbook を修正する(2回目）
```:nginx_install.yml
- hosts: all
  vars:
    ansible_become: yes
    ansible_become_method: sudo
  tasks:
  - name: Install Nginx
    block:
      - name: Install Nginx in block
        yum:
          name: nginx-1.16.0
          state: present
    rescue:
      - debug:
          msg: "Error!"
    always:
      - debug:
          msg: "Always run this section"
```

上記のように修正し、実際に yum で古いバージョンの Nginx が使えるように事前準備します。準備の手順は、[ここ](http://nginx.org/en/linux_packages.html#RHEL-CentOS)を参考にしました。念のため、確認すると、

```:実行結果3
[vagrant@localhost chapter4]$ yum --showduplicates list nginx
(中略)
nginx.x86_64                        1:1.16.1-1.el7                              @epel       
Available Packages
(中略)
nginx.x86_64                        1:1.16.0-1.el7.ngx                          nginx-stable
nginx.x86_64                        1:1.16.1-1.el7                              epel        
nginx.x86_64                        1:1.16.1-1.el7.ngx                          nginx-stabl
```

yum でインストール可能な Nginx のバージョンの一覧が表示されました。
ansible-lint と Dry Run を実行してみます。

```:実行結果4
[vagrant@localhost chapter4]$ ansible-lint nginx_install.yml 
[vagrant@localhost chapter4]$ ansible-playbook -i hosts nginx_install.yml --check

PLAY [all] *********************************************************************************

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

TASK [Install Nginx in block] **************************************************************
changed: [localhost]

TASK [debug] *******************************************************************************
ok: [localhost] => {
    "msg": "Always run this section"
}

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

[vagrant@localhost chapter4]$ 
```

ansible-lint ではエラーが表示されなくなり、古いバージョンの Nginx に変更するため、 PLAY RECAP には change=1 となりました。

##　触っていて、分からなかったこと
 - state=present  
   インストールの状態を維持することを指定していると意味に気づくのに時間がかかりました。
 - --start-at-task  
   ansibleplaybook コマンドで指定できるオプション。指定したタスク名のところから実施できる。
 - playbook の書き方 (name の位置とversionの指定）  
   [公式](https://docs.ansible.com/ansible/latest/modules/yum_module.html)の yum モジュールの name の指定の仕方は以下の通りです。  
   <font color="red">A package name or package specifier with version, like name-1.0. </font>  
   したがって、 name=nginx-1.16.0 と記載しました。  
   name の位置は、いくつかの Playbook を参考に、感覚的に修正してます。
 - ansible-lint では、typo を検知してくれなかったこと  
   state=least と打ち間違えをしましたが、 ansible-lint では構文のエラーを拾ってくれませんでした。  
   後に Dry Run 後に構文のエラーが出力されたため修正しました。  


## 参考文献
 - 八木澤 健人（2019）『Ansible構築・運用ガイドブック インフラ自動化のための現場のノウハウ』,株式会社マイナビ出版,P80-81
 - [Nginx - Installation instructions - RHEL/CentOS](http://nginx.org/en/linux_packages.html#RHEL-CentOS)
 - [CentOSにちょっと古いバージョンのNginxをインストールする](https://qiita.com/segawa/items/bb1d0cd78e890a1e4170)
 - [Ansible - playbooks_intro](https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#playbooks-intro)