wslでansible(2.16.6)ハンズオン

# やること
- Playbookを作成する
- ansible-lintでチェックを行う
- 実行する

### コントロールノード
- Ubuntu 22.04 (on WSL2)
- ansible [core 2.16.6]

### ターゲットノード
- Ubuntu 22.04
- Ubuntu 24.04

記載がない場合、コマンドはすべてコントロールノード上で実行する。
アンダースコア2つで始まるものはプレースホルダです。

```bash
sudo apt update
sudo apt upgrade
sudo apt install ansible
```

### バージョン確認
```bash
ansible --version
```

```
ansible [core 2.16.6]
  config file = None
  configured module search path = ['/home/mari/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/mari/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/mari/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/mari/.local/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.0.3
  libyaml = True
```

### ansible-lintのインストール
```bash
ansible-lint --version
```

```
ansible-lint 24.5.0 using ansible-core:2.16.6 ansible-compat:24.5.1 ruamel-yaml:0.18.6 ruamel-yaml-clib:0.2.8
```


### hosts.yamlを作成する
```yaml
---
all:
  vars:
    ansible_user: __username__
    ansible_password: __password__
  hosts:
    elysium:
      ansible_host: __target1_ip__
      ansible_become_password: __target1_root_password__
    hexdrinker:
      ansible_host: __target2_ip__
      ansible_port: __target2_port__
      ansible_become_password: __target2_root_password__
      ansible_ssh_private_key_file: ~/.ssh/id_rsa
```
公開鍵認証とパスワード認証の二通りを試してみる。

### Playbookを作成する
- apt update
- rootユーザの作成
- cronに週次で再起動スケジュールを設定(日曜日0時)
- cron.dailyに日次でapt-get update / apt-get upgradeを行うスクリプトを作成して配置
- タイムゾーンとロケールの設定
- python3.12のインストール
- dockerのインストール
- 再起動(ロケールの変更が行われた場合のみ)

```bash
vim setup-ubuntu.yaml
```


```YAML
---
- name: Setup Ubuntu machine
  hosts: all
  become: true

  tasks:
    # apt update
    - name: Update apt
      ansible.builtin.apt:
        update_cache: true
    # rootを有効化
    - name: Enable root user
      ansible.builtin.user:
        name: root
        shell: /bin/bash
    # rootにパスワードを設定
    - name: Ensure root has a password
      ansible.builtin.user:
        name: root
        password: "{{ '__password__' | password_hash('sha512') }}"
        update_password: on_create
    # cronに週次で再起動を行う設定を追加
    - name: Add cron job for weekly reboot
      ansible.builtin.cron:
        name: "Weekly reboot"
        special_time: weekly
        job: "/sbin/shutdown -r now"
    # cron.dailyにapt update / apt upgradeを行うスクリプトを追加
    - name: Create apt script for auto-update and upgrade
      ansible.builtin.copy:
        dest: /etc/cron.daily/apt-update-upgrade
        content: |
          #!/bin/sh
          apt-get update && apt-get -y upgrade
        mode: '0755'
    # タイムゾーンを設定
    - name: Set timezone to Asia/Tokyo
      community.general.timezone:
        name: Asia/Tokyo
    # 日本語設定
    - name: Install Japanese locale
      community.general.locale_gen:
        name: ja_JP.UTF-8
        state: present
    # ロケールを変更(変更した場合は再起動)
    - name: Ensure the locale file has the correct LANG setting
      ansible.builtin.lineinfile:
        path: /etc/default/locale
        regexp: '^LANG='
        line: 'LANG=ja_JP.UTF-8'
      notify: Reboot system
    # python 3.12をインストール
    - name: Install Python 3.12
      ansible.builtin.apt:
        name: python3.12
        state: present
        update_cache: true
    # dockerインストール
    - name: Install prerequisites for Docker
      ansible.builtin.apt:
        name:
          - apt-transport-https
          - ca-certificates
          - curl
          - software-properties-common
        state: present

    - name: Add Docker GPG key
      ansible.builtin.apt_key:
        url: https://download.docker.com/linux/ubuntu/gpg
        state: present

    - name: Add Docker repository
      ansible.builtin.apt_repository:
        repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
        state: present

    - name: Update apt and install docker
      ansible.builtin.apt:
        update_cache: true
        name: docker-ce
        state: present

  handlers:
    # システムの再起動
    - name: Reboot system
      ansible.builtin.reboot:
        msg: "Rebooting after locale change"
        pre_reboot_delay: 5
        post_reboot_delay: 30
        reboot_timeout: 600
```

#### キーワード
- become
    - 管理者権限で実行するか否か。今回は先頭に記載しているが、タスク(?)毎に設定したりできるっぽい。

- ansible.builtin.apt
    - 古い記事を参照するとaptとかcopyとかモジュール名だけで記載していることが多いけど、直近だとこれは非推奨っぽい(ansible-lintがブチ切れる)のでFQCNで記載してあげる。

- notify
    - changedが発生した場合、ここに記載されているhandlersを呼び出す。

- ansible.builtin.commandとansible.builtin.shellの冪等性
    - こいつらは冪等性を自分で確保してあげないとansible-lintがブチ切れるので、条件付き実行してあげたりする必要がある。
    - 当初ロケールの変更はcommandで実行していたが、冪等性の確保ができていなかったため、ansible.builtin.lineinfileにて変更するようにした。


### プレイブックの書式チェック
```bash
ansible-playbook -i hosts.yaml setup-ubuntu.yaml --syntax-check
```


### ansible-lintでプレイブックの書式をチェック

```bash
ansible-lint setup-ubuntu.yaml 
```

以下はplaybook作成途中に発生した警告
- name[casing]: All names should start with an uppercase letter
    - nameは大文字で始めろ！
    - 「apt updateを実行する」とか書くとこの警告に引っかかるので全部英語で記載した。もちろん警告なので無視しても良い。
- yaml[trailing-spaces]: Trailing spaces
    - いらん空白が存在してる。

そのほかにも先述したFQCNで記載していないと警告がでたりする。今から始める人はモジュール名はFQCNで記載しよう。

```bash
WARNING  Listing 3 violation(s) that are fatal
name[casing]: All names should start with an uppercase letter.
setup-ubuntu.yaml:7 Task/Handler: apt updateを実行します

name[casing]: All names should start with an uppercase letter.
setup-ubuntu.yaml:84 Task/Handler: apt updateしてdockerをインストールする

yaml[trailing-spaces]: Trailing spaces
setup-ubuntu.yaml:89

Read documentation for instructions on how to ignore specific rule violations.

                  Rule Violation Summary
 count tag                   profile  rule associated tags 
     1 yaml[trailing-spaces] basic    formatting, yaml
     2 name[casing]          moderate idiom
```

なにも警告がなければ以下のような出力がなされる。

```bash
Passed: 0 failure(s), 0 warning(s) on 1 files. Last profile that met the validation criteria was 'production'.
```


### タスクを実行する
```bash
ansible-playbook -i hosts.yaml setup-ubuntu.yaml
```

変更があればchanged、なければokって感じでログが出力されてく。

自分の環境では片方のノードにてpythonインストールが失敗していた。
そしてどうやらfatalが出てしまうとそのノードでの以降の処理が行われないっぽい。
pythonインストール処理をコメントアウトして再実行した結果、それ以外の処理は問題なく完了した。

##### 警告「Encryption using the Python crypt module is deprecated」について
コントロールノードにてpathlibをインストールしてやればよいっぽい
```bash
python3 -m pip install passlib
```