WSL上にansibleを導入する with python3

# やりたいこと
WSL上にansibleを導入したい。pythonのバージョンとかとりあえず新しいっぽいやつ使いたい。

# 前提知識
## ansibleって何よ？
A というPC(管理ホスト) から B という PC (被管理ホスト。複数指定できる) へ ssh でいろんな命令を飛ばすことで構成管理を行うツール。

冪等性 (べきとうせい。同じ操作を何度やっても最終的な状態が同じになる性質) を持つ。
管理ホスト と 被管理ホストが同じ (対象がlocalhost) も可能で、その場合はsshの設定は不要。
ここがわかりやすいので読んでおこう。
[ansibleの基礎知識](https://www.atmarkit.co.jp/ait/articles/1603/24/news014.html)

## ansibleの主たる構成要素
### インベントリファイル
被管理ホストへの接続情報(host名、ssh ユーザー、ssh 秘密鍵ファイルパス、sudoパスワード、sudoユーザー名等)を書くファイル。
localhostへの実行にしか使用しない場合は不要。

### モジュール
ユーザーを追加する、ファイルをコピーするなどの冪等性を持ったansible上の操作。
数百のモジュールがあらかじめ用意されている。
[モジュール一覧](https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html)

### プレイブック
上記のモジュールを組み合わせて作った手順書。

## んでansibleとpythonの関係は、、
ansibleは python が入ってるマシンで動きます。
管理マシンと被管理マシン両方にpythonが入っている必要があることに注意。

# aptコマンド毎回忘れる人(私)のための参考ページ
https://linuxfan.info/package-management-ubuntu

# WSLのバージョン
Ubuntu 18.04.1 LTS

```bash
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
```

# ansible をpython3で入れるにはどうしたらいいのよ？
[まずは公式](https://docs.ansible.com/ansible/latest/reference_appendices/python_3_support.html)
pip3 (pythonのバージョン管理ツール)を使えばよいとのこと。
Controller side :管理ホスト
Managed Machines:非管理ホスト
のことだと思われる。

> On the controller side
The easiest way to run /usr/bin/ansible under Python 3 is to install it with the Python3 version of pip. This will make the default /usr/bin/ansible run with Python3:

>```bash
$ pip3 install ansible
$ ansible --version | grep "python version"
  python version = 3.6.2 (default, Sep 22 2017, 08:28:09) [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)]
```

# pip3のインストール
https://qiita.com/tkj06/items/22947c6fe63acf24ae97

# ansibleのインストール
```bash:pip3によるansibleインストール
$ pip3 install ansible
Collecting ansible
  Downloading https://files.pythonhosted.org/packages/9a/9d/5e3d67bd998236f32a72f255394eccd1e22b3e2843aa60dc30dd164816d0/ansible-2.7.10.tar.gz (11.8MB)
    100% |████████████████████████████████| 11.8MB 129kB/s
Collecting PyYAML (from ansible)
  Downloading https://files.pythonhosted.org/packages/9f/2c/9417b5c774792634834e730932745bc09a7d36754ca00acf1ccd1ac2594d/PyYAML-5.1.tar.gz (274kB)
    100% |████████████████████████████████| 276kB 2.1MB/s
Collecting cryptography (from ansible)
  Downloading https://files.pythonhosted.org/packages/5b/12/b0409a94dad366d98a8eee2a77678c7a73aafd8c0e4b835abea634ea3896/cryptography-2.6.1-cp34-abi3-manylinux1_x86_64.whl (2.3MB)
    100% |████████████████████████████████| 2.3MB 537kB/s
Collecting jinja2 (from ansible)
  Downloading https://files.pythonhosted.org/packages/1d/e7/fd8b501e7a6dfe492a433deb7b9d833d39ca74916fa8bc63dd1a4947a671/Jinja2-2.10.1-py2.py3-none-any.whl (124kB)
    100% |████████████████████████████████| 133kB 4.3MB/s
Collecting paramiko (from ansible)
  Downloading https://files.pythonhosted.org/packages/cf/ae/94e70d49044ccc234bfdba20114fa947d7ba6eb68a2e452d89b920e62227/paramiko-2.4.2-py2.py3-none-any.whl (193kB)
    100% |████████████████████████████████| 194kB 4.0MB/s
Collecting setuptools (from ansible)
  Downloading https://files.pythonhosted.org/packages/c8/b0/cc6b7ba28d5fb790cf0d5946df849233e32b8872b6baca10c9e002ff5b41/setuptools-41.0.0-py2.py3-none-any.whl (575kB)
    100% |████████████████████████████████| 583kB 2.4MB/s
Collecting cffi!=1.11.3,>=1.8 (from cryptography->ansible)
  Downloading https://files.pythonhosted.org/packages/5f/bf/6aa1925384c23ffeb579e97a5569eb9abce41b6310b329352b8252cee1c3/cffi-1.12.3-cp36-cp36m-manylinux1_x86_64.whl (430kB)
    100% |████████████████████████████████| 440kB 1.1MB/s
Collecting asn1crypto>=0.21.0 (from cryptography->ansible)
  Downloading https://files.pythonhosted.org/packages/ea/cd/35485615f45f30a510576f1a56d1e0a7ad7bd8ab5ed7cdc600ef7cd06222/asn1crypto-0.24.0-py2.py3-none-any.whl (101kB)
    100% |████████████████████████████████| 102kB 3.4MB/s
Collecting six>=1.4.1 (from cryptography->ansible)
  Downloading https://files.pythonhosted.org/packages/73/fb/00a976f728d0d1fecfe898238ce23f502a721c0ac0ecfedb80e0d88c64e9/six-1.12.0-py2.py3-none-any.whl
Collecting MarkupSafe>=0.23 (from jinja2->ansible)
  Downloading https://files.pythonhosted.org/packages/b2/5f/23e0023be6bb885d00ffbefad2942bc51a620328ee910f64abe5a8d18dd1/MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl
Collecting pynacl>=1.0.1 (from paramiko->ansible)
  Downloading https://files.pythonhosted.org/packages/27/15/2cd0a203f318c2240b42cd9dd13c931ddd61067809fee3479f44f086103e/PyNaCl-1.3.0-cp34-abi3-manylinux1_x86_64.whl (759kB)
    100% |████████████████████████████████| 768kB 1.3MB/s
Collecting pyasn1>=0.1.7 (from paramiko->ansible)
  Downloading https://files.pythonhosted.org/packages/7b/7c/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c/pyasn1-0.4.5-py2.py3-none-any.whl (73kB)
    100% |████████████████████████████████| 81kB 4.4MB/s
Collecting bcrypt>=3.1.3 (from paramiko->ansible)
  Downloading https://files.pythonhosted.org/packages/d0/79/79a4d167a31cc206117d9b396926615fa9c1fdbd52017bcced80937ac501/bcrypt-3.1.6-cp34-abi3-manylinux1_x86_64.whl (55kB)
    100% |████████████████████████████████| 61kB 3.7MB/s
Collecting pycparser (from cffi!=1.11.3,>=1.8->cryptography->ansible)
  Downloading https://files.pythonhosted.org/packages/68/9e/49196946aee219aead1290e00d1e7fdeab8567783e83e1b9ab5585e6206a/pycparser-2.19.tar.gz (158kB)
    100% |████████████████████████████████| 163kB 3.2MB/s
Building wheels for collected packages: ansible, PyYAML, pycparser
  Running setup.py bdist_wheel for ansible ... done
  Stored in directory: /home/unix_user/.cache/pip/wheels/b1/87/37/8f982acaa4fd348505aa36789e2273ee362dbce98716d14cba
  Running setup.py bdist_wheel for PyYAML ... done
  Stored in directory: /home/unix_user/.cache/pip/wheels/ad/56/bc/1522f864feb2a358ea6f1a92b4798d69ac783a28e80567a18b
  Running setup.py bdist_wheel for pycparser ... done
  Stored in directory: /home/unix_user/.cache/pip/wheels/f2/9a/90/de94f8556265ddc9d9c8b271b0f63e57b26fb1d67a45564511
Successfully built ansible PyYAML pycparser
Installing collected packages: PyYAML, pycparser, cffi, asn1crypto, six, cryptography, MarkupSafe, jinja2, pynacl, pyasn1, bcrypt, paramiko, setuptools, ansible
Successfully installed MarkupSafe-1.1.1 PyYAML-5.1 ansible-2.7.10 asn1crypto-0.24.0 bcrypt-3.1.6 cffi-1.12.3 cryptography-2.6.1 jinja2-2.10.1 paramiko-2.4.2 pyasn1-0.4.5 pycparser-2.19 pynacl-1.3.0 setuptools-41.0.0 six-1.12.0
```

インストール後確認

```bash:インストール後確認
$ pip3 show ansible
Name: ansible
Version: 2.7.10
Summary: Radically simple IT automation
Home-page: https://ansible.com/
Author: Ansible, Inc.
Author-email: info@ansible.com
License: GPLv3+
Location: /home/unix_user/.local/lib/python3.6/site-packages
Requires: cryptography, setuptools, jinja2, paramiko, PyYAML

$ ansible --version

# あれ？
Command 'ansible' not found, but can be installed with:

sudo apt install ansible
```

一回exitしてbash立ち上げなおしたらok 

```bash
$ ansible --version
ansible 2.7.10
  config file = None
  configured module search path = ['/home/unix_user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/unix_user/.local/lib/python3.6/site-packages/ansible
  executable location = /home/unix_user/.local/bin/ansible
  python version = 3.6.7 (default, Oct 22 2018, 11:32:17) [GCC 8.2.0]
```

# ansibleをlocalhostに対して実行
```bash:playbook
$ cat playbook.yaml
- hosts: localhost
  tasks:
    - ping:
```

```bash:inventoryファイルがないよ警告は出るが成功
$ ansible-playbook playbook.yaml
 [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match
'all'


PLAY [localhost] *******************************************************************************************************

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

TASK [ping] ************************************************************************************************************
ok: [localhost]

PLAY RECAP *************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0
```

# ansibleのアンインストール
```bash:ansibleをpip3でアンインストール
$ pip3 uninstall ansible
Uninstalling ansible-2.7.10:
  /home/unix_user/.local/bin/ansible
  /home/unix_user/.local/bin/ansible-config

# すごいたくさんのファイルが続く~~~~

  /home/unix_user/.local/lib/python3.6/site-packages/ansible/vars/unsafe_proxy.py
Proceed (y/n)? y
  Successfully uninstalled ansible-2.7.10
```

## アンインストール確認

```bash:ansibleアンインストール確認
$ pip3 freeze
asn1crypto==0.24.0
attrs==17.4.0
Automat==0.6.0
bcrypt==3.1.6
blinker==1.4
certifi==2018.1.18
cffi==1.12.3
chardet==3.0.4
click==6.7
cloud-init==18.2
colorama==0.3.7
command-not-found==0.3
configobj==5.0.6
constantly==15.1.0
cryptography==2.6.1
distro-info==0.18
httplib2==0.9.2
hyperlink==17.3.1
idna==2.6
incremental==16.10.1
Jinja2==2.10.1
jsonpatch==1.16
jsonpointer==1.10
jsonschema==2.6.0
keyring==10.6.0
keyrings.alt==3.0
language-selector==0.1
MarkupSafe==1.1.1
oauthlib==2.0.6
PAM==0.4.2
paramiko==2.4.2
pyasn1==0.4.5
pyasn1-modules==0.2.1
pycparser==2.19
pycrypto==2.6.1
pygobject==3.26.1
PyJWT==1.5.3
PyNaCl==1.3.0
pyOpenSSL==17.5.0
pyserial==3.4
python-apt==1.6.2
python-debian==0.1.32
pyxdg==0.25
PyYAML==5.1
requests==2.18.4
requests-unixsocket==0.1.5
SecretStorage==2.3.1
service-identity==16.0.0
six==1.12.0
ssh-import-id==5.7
systemd-python==234
Twisted==17.9.0
ufw==0.35
unattended-upgrades==0.1
urllib3==1.22
zope.interface==4.3.2

$ ansible

Command 'ansible' not found, but can be installed with:

sudo apt install ansible
```

# おまけ ansibleのexecutable locationを/usr/local/bin にしたい場合
pip3 ではなくLinuxのsudoの特性ではあるが、上記の方法でansibleをインストールすると`sudo ansible-playbook`などで `sudo: command not found`といったエラーになる。

## 原因
sudo コマンドでユーザが切り替わるので、$PATHが変わってしまうから。
[参考:sudo時のPATHについて](https://blog.thingslabo.com/archives/000395.html)

>sudoers の env_reset オプションが有効になっている場合、セキュリティ上環境変数が初期化されて secure_path に設定しているパスが使われるので、環境変数 PATH が通らない。

```bash:sudo設定ファイル(/etc/sudoers)
$ sudo cat /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
# env_resetで、環境変数が初期化されて secure_path に設定しているパスが使われる
Defaults        env_reset 
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d
```

## 結局どうすればいいんだ！
pip3でansibleをインストールするときに`sudo pip3 install ansible`します。
ただし、sudo実行時に環境変数$HOMEだけsudo後のユーザーの設定を使うオプション`sudo -H`を使います。
[参考:sudo -H](https://diary.masasuzu.net/entry/2015/01/20/sudo_-H%E3%81%A8%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%28%24PATH%29%E3%81%A7%E3%81%AF%E3%81%BE%E3%81%A3%E3%81%9F%E8%A9%B1)

```bash:pip3をsudoで実行
$ sudo -H pip3 install ansible
Collecting ansible
  Downloading https://files.pythonhosted.org/packages/9a/9d/5e3d67bd998236f32a72f255394eccd1e22b3e2843aa60dc30dd164816d0/ansible-2.7.10.tar.gz (11.8MB)
    100% |████████████████████████████████| 11.8MB 143kB/s
Requirement already satisfied: PyYAML in /usr/lib/python3/dist-packages (from ansible)
Requirement already satisfied: cryptography in /usr/lib/python3/dist-packages (from ansible)
Requirement already satisfied: jinja2 in /usr/lib/python3/dist-packages (from ansible)
Collecting paramiko (from ansible)
  Downloading https://files.pythonhosted.org/packages/cf/ae/94e70d49044ccc234bfdba20114fa947d7ba6eb68a2e452d89b920e62227/paramiko-2.4.2-py2.py3-none-any.whl (193kB)
    100% |████████████████████████████████| 194kB 1.2MB/s
Requirement already satisfied: setuptools in /usr/lib/python3/dist-packages (from ansible)
Collecting pynacl>=1.0.1 (from paramiko->ansible)
  Downloading https://files.pythonhosted.org/packages/27/15/2cd0a203f318c2240b42cd9dd13c931ddd61067809fee3479f44f086103e/PyNaCl-1.3.0-cp34-abi3-manylinux1_x86_64.whl (759kB)
    100% |████████████████████████████████| 768kB 1.1MB/s
Collecting bcrypt>=3.1.3 (from paramiko->ansible)
  Downloading https://files.pythonhosted.org/packages/d0/79/79a4d167a31cc206117d9b396926615fa9c1fdbd52017bcced80937ac501/bcrypt-3.1.6-cp34-abi3-manylinux1_x86_64.whl (55kB)
    100% |████████████████████████████████| 61kB 2.2MB/s
Requirement already satisfied: pyasn1>=0.1.7 in /usr/lib/python3/dist-packages (from paramiko->ansible)
Requirement already satisfied: six in /usr/lib/python3/dist-packages (from pynacl>=1.0.1->paramiko->ansible)
Collecting cffi>=1.4.1 (from pynacl>=1.0.1->paramiko->ansible)
  Downloading https://files.pythonhosted.org/packages/5f/bf/6aa1925384c23ffeb579e97a5569eb9abce41b6310b329352b8252cee1c3/cffi-1.12.3-cp36-cp36m-manylinux1_x86_64.whl (430kB)
    100% |████████████████████████████████| 440kB 2.5MB/s
Collecting pycparser (from cffi>=1.4.1->pynacl>=1.0.1->paramiko->ansible)
  Downloading https://files.pythonhosted.org/packages/68/9e/49196946aee219aead1290e00d1e7fdeab8567783e83e1b9ab5585e6206a/pycparser-2.19.tar.gz (158kB)
    100% |████████████████████████████████| 163kB 3.3MB/s
Building wheels for collected packages: ansible, pycparser
  Running setup.py bdist_wheel for ansible ... done
  Stored in directory: /root/.cache/pip/wheels/b1/87/37/8f982acaa4fd348505aa36789e2273ee362dbce98716d14cba
  Running setup.py bdist_wheel for pycparser ... done
  Stored in directory: /root/.cache/pip/wheels/f2/9a/90/de94f8556265ddc9d9c8b271b0f63e57b26fb1d67a45564511
Successfully built ansible pycparser
Installing collected packages: pycparser, cffi, pynacl, bcrypt, paramiko, ansible
Successfully installed ansible-2.7.10 bcrypt-3.1.6 cffi-1.12.3 paramiko-2.4.2 pycparser-2.19 pynacl-1.3.0
```

確認

```bash
$ ansible --version
ansible 2.7.10
  config file = None
  configured module search path = ['/home/unix_user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/dist-packages/ansible
  executable location = /usr/local/bin/ansible # sudo時にもPATHが通る
  python version = 3.6.7 (default, Oct 22 2018, 11:32:17) [GCC 8.2.0]

$ pip3 show ansible
Name: ansible
Version: 2.7.10
Summary: Radically simple IT automation
Home-page: https://ansible.com/
Author: Ansible, Inc.
Author-email: info@ansible.com
License: GPLv3+
Location: /usr/local/lib/python3.6/dist-packages
Requires: PyYAML, setuptools, paramiko, jinja2, cryptography
```

### -H がないと、、、
警告が出て若干変な感じになります。動きはするみたいですが。。
pipが使用するキャッシュの置き場がユーザのhomeディレクトリ配下みたいですが、所有者がちげーぞって言われちゃいます。

```bash
$ sudo pip3 install ansible
The directory '/home/unix_user/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/unix_user/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting ansible
Requirement already satisfied: setuptools in /home/unix_user/.local/lib/python3.6/site-packages (from ansible)
Requirement already satisfied: jinja2 in /home/unix_user/.local/lib/python3.6/site-packages (from ansible)
Requirement already satisfied: paramiko in /home/unix_user/.local/lib/python3.6/site-packages (from ansible)
Requirement already satisfied: PyYAML in /home/unix_user/.local/lib/python3.6/site-packages (from ansible)
Requirement already satisfied: cryptography in /home/unix_user/.local/lib/python3.6/site-packages (from ansible)
Requirement already satisfied: MarkupSafe>=0.23 in /home/unix_user/.local/lib/python3.6/site-packages (from jinja2->ansible)
Requirement already satisfied: pyasn1>=0.1.7 in /home/unix_user/.local/lib/python3.6/site-packages (from paramiko->ansible)
Requirement already satisfied: pynacl>=1.0.1 in /home/unix_user/.local/lib/python3.6/site-packages (from paramiko->ansible)
Requirement already satisfied: bcrypt>=3.1.3 in /home/unix_user/.local/lib/python3.6/site-packages (from paramiko->ansible)
Requirement already satisfied: six>=1.4.1 in /home/unix_user/.local/lib/python3.6/site-packages (from cryptography->ansible)
Requirement already satisfied: cffi!=1.11.3,>=1.8 in /home/unix_user/.local/lib/python3.6/site-packages (from cryptography->ansible)
Requirement already satisfied: asn1crypto>=0.21.0 in /home/unix_user/.local/lib/python3.6/site-packages (from cryptography->ansible)
Requirement already satisfied: pycparser in /home/unix_user/.local/lib/python3.6/site-packages (from cffi!=1.11.3,>=1.8->cryptography->ansible)
Installing collected packages: ansible
Successfully installed ansible-2.7.10
```