【ルール説明・basic】command-instead-of-module・command-instead-of-shell

こちらの記事は[Ansible lint Advent Calendar 2022](https://qiita.com/mamono210/items/a5a83eb1b9f838713e90) 10日目の記事になります。

今回はルール[command-instead-of-module](https://ansible-lint.readthedocs.io/rules/command-instead-of-module/)および[command-instead-of-shell](https://ansible-lint.readthedocs.io/rules/command-instead-of-shell/)について説明します。

### command-instead-of-module

[ansible.builtin.command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html)モジュールを利用する際コマンドにAnsibleモジュールで代替できるようなコマンドが含まれているか検査します。もし含まれている場合はエラーを出力します。

代替を提示されるコマンドは以下です。Ansible lintの[ソースコード](https://github.com/ansible/ansible-lint/blob/main/src/ansiblelint/rules/command_instead_of_module.py)より確認できます。

| コマンド | 代替モジュール |
| --- | --- |
| apt-get | [ansible.builtin.apt](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html) |
| chkconfig | [ansible.builtin.service](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_module.html) |
| curl | [ansible.builtin.get_url](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/get_url_module.html) / [ansible.builtin.uri](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/uri_module.html) |
| git | [ansible.builtin.git](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/git_module.html) |
| hg | [community.general.hg](https://docs.ansible.com/ansible/latest/collections/community/general/hg_module.html) |
| letsencrypt | [community.crypto.acme_certificate](https://docs.ansible.com/ansible/latest/collections/community/crypto/acme_certificate_module.html) |
| mktemp | [ansible.builtin.tempfile](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/tempfile_module.html) |
| mount | [ansible.posix.mount](https://docs.ansible.com/ansible/latest/collections/ansible/posix/mount_module.html) |
| patch | [ansible.posix.patch](https://docs.ansible.com/ansible/latest/collections/ansible/posix/patch_module.html) |
| rpm | [ansible.builtin.yum](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/yum_module.html) / [ansible.builtin.rpm_key](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/rpm_key_module.html) |
| rsync | [ansible.posix.synchronize](https://docs.ansible.com/ansible/latest/collections/ansible/posix/synchronize_module.html) |
| sed | [ansible.builtin.template](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.html) / [ansible.builtin.replace](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html) / [ansible.builtin.lineinfile](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html) |
| service | [ansible.builtin.service](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_module.html) |
| supervisorctl | [community.general.supervisorctl](https://docs.ansible.com/ansible/latest/collections/community/general/supervisorctl_module.html) |
| svn | [ansible.builtin.subversion](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/subversion_module.html) |
| systemctl | [ansible.builtin.systemd](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/systemd_module.html) |
| tar | [ansible.builtin.unarchive](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/unarchive_module.html) |
| unzip | [ansible.builtin.unarchive](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/unarchive_module.html) |
| wget | [ansible.builtin.get_url](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/get_url_module.html) / [ansible.builtin.uri](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/uri_module.html) |
| yum | [ansible.builtin.yum](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/yum_module.html) |

#### 問題のあるコード

```yaml
---
- name: Update apt cache
  hosts: all
  tasks:
    - name: Run apt-get update
      ansible.builtin.command: apt-get update # <-- better to use ansible.builtin.apt module
```

#### 修正されたコード

```yaml
---
- name: Update apt cache
  hosts: all
  tasks:
    - name: Run apt-get update
      ansible.builtin.apt:
        update_cache: true
```

### command-instead-of-shell

[ansible.builtin.shell](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html)モジュールではなく[ansible.builtin.command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html)モジュールを利用するように警告を出力します。[ansible.builtin.shell](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html)モジュールは[ansible.builtin.command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html)モジュールに比べて動作が遅く特殊な使い方（環境変数を設定したりパイプを利用する等）をしない限りは[ansible.builtin.command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html)モジュールを利用するのが良いとされています。

#### 問題のあるコード

```yaml
---
- name: Problematic example
  hosts: localhost
  tasks:
    - name: Echo a message
      ansible.builtin.shell: echo hello # <-- command is better in this case
      changed_when: false
```

#### 修正されたコード

```yaml
---
- name: Correct example
  hosts: localhost
  tasks:
    - name: Echo a message
      ansible.builtin.command: echo hello
      changed_when: false
```

### 参考サイト

* [command-instead-of-module — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/command-instead-of-module/)
* [command-instead-of-shell — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/command-instead-of-shell/)。