Ansibleをインベントリファイルなしで使おう

# はじめに

Ansibleを実行する際に、ホスト名とか書いたインベントリファイルが必ず必要だと思っていないだろうか。

Ansibleではインベントリファイルに書いていなくても操作対象にできるホストが1つだけある。それはlocalhostだ。
つまり、操作対象がlocalhostただ1つだけの場合、インベントリファイルなんて書く必要は全然ない。

さらにlocalhostを操作する場合はSSHを使わないので、鍵がどうの、パスワードがどうのという話ともまったく無縁。

というわけで、インベントリファイルを書くのも面倒くさがるようなものぐささんであっても、Ansibleをインストールするだけで自コンピュータのちょっとした設定変更ができるよ、というお話。

**2014-12-31追記**: localhostだけでなく他のコンピュータも操作できることがわかったので、別途記事を書いた。
http://qiita.com/yunano/items/a72b4e0289bb17c14451

**2015-06-28追記**: 今更気付いたがインベントリファイルを指定する-iオプションがなくても上手く行くのは、インベントリファイルのパスのデフォルト値である /etc/ansible/hosts が使われるからだ。そしてEPELからインストールすると /etc/ansible/hosts が配置される一方、pipからインストールすると /etc/ansible/hosts は配置されず-iオプションを省略すると「ERROR: Unable to find an inventory file, specify one with -i ?」エラーになる。しかし-iオプションはインベントリファイルを代わりにカンマが入っている文字列を指定できるので（本来はホスト名をカンマ区切りで列記するためのもの）、/etc/ansible/hosts がないために以下の方法がlocalhostを相手にしているだけなのにエラーになる場合は-iオプションに意味のないカンマを含む文字列を指定、例えば「-i @,」を追加すると良い。

# やってみる

## その1

それでは早速、CentOSユーザの99%（適当）が実施するというあれをやってみる。

```
# ansible localhost -m selinux -a state=disabled

（ここから出力）
localhost | success >> {
    "changed": true,
    "configfile": "/etc/selinux/config",
    "msg": "state change will take effect next reboot, config state changed from 'enforcing' to 'disabled'",
    "policy": "targeted",
    "state": "disabled"
}
```

localhost相手だとfact取得しに行かないのですぐ終わる。
出力に「"changed": true」とあるから何か書き換わったことがわかるね。
あと"msg"に、'enforcing'から'disabled'に実際に変わるのは再起動した後だよ、って書いてある。これは手で書き換えた時も同じだね。

実際に以下のように書き換わっている。

```text:/etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
```

もちろんalias使えばもっと短くできる。

```
# alias lcans='ansible localhost -m '
# lcans selinux -a state=disabled
```

permissiveにするのはpolicy（/etc/selinux/configにおけるSELINUXTYPE）指定しないといけないのでちょっとだけ面倒。

```
# lcans selinux -a 'state=permissive policy=targeted'
```

ちなみにselinuxモジュールの実行にはlibselinux-pythonパッケージがインストールされている必要がある。
CentOS 7では「最小限のインストール」でもlibselinux-pythonはインストールされているが、CentOS 6ではインストールされないのでansibleをインストールする時に一緒にインストールしておくと良い。

下はものぐさコピペ用。
AnsibleはEPELにあるので、先にepel-releaseインストールしてね。

```
yum install -y epel-release
yum install -y ansible libselinux-python
```

## その2

次。iniファイル書き換えたいことあるよね。
例えば、epel-testingリポジトリでも有効にしてみよう。

（さっき作ったaliasを使って）

```
# lcans ini_file -a 'dest=/etc/yum.repos.d/epel-testing.repo section=epel-testing option=enabled value=1'

（ここから出力）
localhost | success >> {
    "changed": true,
    "dest": "/etc/yum.repos.d/epel-testing.repo",
    "gid": 0,
    "group": "root",
    "mode": "0644",
    "msg": "OK",
    "owner": "root",
    "secontext": "system_u:object_r:system_conf_t:s0",
    "size": 875,
    "state": "file",
    "uid": 0
}
```

こっちも出力に「"changed": true」とあるから何か書き換わったことがわかるね。

実際にこう書き換わっている。
値が書き換わっただけではなくて、元の /etc/yum.repos.d/epel-testing.repo には"="の前後にスペースはなかったけど、実行後はスペースが入っている。それでもまあiniファイル的には問題なく使える。

```text:/etc/yum.repos.d/epel-testing.repo
[epel-testing]
name = Extra Packages for Enterprise Linux 7 - Testing - $basearch
mirrorlist = https://mirrors.fedoraproject.org/metalink?repo=testing-epel7&arch=$basearch
failovermethod = priority
enabled = 1
gpgcheck = 1
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

[epel-testing-debuginfo]
name = Extra Packages for Enterprise Linux 7 - Testing - $basearch - Debug
mirrorlist = https://mirrors.fedoraproject.org/metalink?repo=testing-debug-epel7&arch=$basearch
failovermethod = priority
enabled = 0
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck = 1

[epel-testing-source]
name = Extra Packages for Enterprise Linux 7 - Testing - $basearch - Source
mirrorlist = https://mirrors.fedoraproject.org/metalink?repo=testing-source-epel7&arch=$basearch
failovermethod = priority
enabled = 0
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck = 1
```

こんなのエディタ使った方が早い？ コピペで実行できる方が早いんじゃないかな。
sed? awk? enabledはセクションごとにあるからちょっと面倒だよね。
crudini? ……あー、うん。まあ専用ツールには使い勝手は負ける、かな。

## その3

sysctl。永続化するには /etc/sysctl.conf とかに書かないといけないし、今反映させたければ`sysctl -w`でセットしないといけない。
両方いっぺんにやってくれると嬉しいよね。というわけでAnsibleの出番。

```
# lcans sysctl -a 'name=net.ipv4.ip_forward value=1'

（ここから出力）
localhost | success >> {
    "changed": true
}
```

/etc/sysctl.conf変わってる。

```text:/etc/sysctl.conf
# System default settings live in /usr/lib/sysctl.d/00-system.conf.
# To override those settings, enter new settings here, or in an /etc/sysctl.d/<name>.conf file
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
net.ipv4.ip_forward = 1
```

現在の値も変わってる。

```
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
```

# ほかにも

[モジュール一覧](http://docs.ansible.com/list_of_all_modules.html)ざっと眺めてみて、cronとかfilesystemとかhostnameとかmodprobeとかmountとかserviceとかunarchiveとかは普通にコマンド打つよりAnsible使った方が楽かもねと思った。
ざっと見ただけなので、まだ他にも使えそうなのあるんじゃないかな。
挙げたのも使ってみたわけではないので、そんなに使い勝手良くないのもあるかもしれないけど。