Ansibleで trick or treat🎃

Ansibleの`when`の条件指定、あまり得意ではない(あまり使わないから)ので思い付きでいろいろ試してみた！

# trick or treat

まずは無邪気に書いてみる(失敗版)

```yaml
---
- hosts: localhost
  tasks:
  - debug:
      msg: Happy Halloween
    when: trick or treat
```

```
[zaki@manager halloween]$ ansible-playbook playbook.yml -e trick=True -e treat=False
 [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 [debug] *******************************************************************
ok: [localhost] => 
  msg: Happy Halloween

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

[zaki@manager halloween]$ 
```

お、動く…
と思ったんだけど、

```
[zaki@manager halloween]$ ansible-playbook playbook.yml -e trick=False -e treat=False
 [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 [debug] *******************************************************************
ok: [localhost] => 
  msg: Happy Halloween

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

[zaki@manager halloween]$ 
```

`trick:false and treat:false`でも動く。これじゃダメだ。  
これがなぜダメなのかは時間があれば調べよう…

## boolにキャスト

(キャストって言い方でいいんだっけ)

```yaml
---
- hosts: localhost
  tasks:
  - debug:
      msg: Happy Halloween
    when: trick|bool or treat|bool
```

これだと

```
[zaki@manager halloween]$ ansible-playbook playbook.yml -e trick=False -e treat=False
 [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 [debug] *******************************************************************
skipping: [localhost]

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

[zaki@manager halloween]$ 
```

お、期待通り。  
(true/true, false/true, true/falseも大丈夫)

## 定義済みチェック

ただしこのままだと、`trick`と`treat`が定義済みでなければエラーになってしまう。

```
[zaki@manager halloween]$ ansible-playbook playbook.yml
 [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 [debug] *******************************************************************
fatal: [localhost]: FAILED! => 
  msg: |-
    The conditional check 'trick|bool or treat|bool' failed. The error was: error while evaluating conditional (trick|bool or treat|bool): 'trick' is undefined
  
    The error appears to be in '/home/zaki/work/ansible/halloween/playbook.yml': line 4, column 5, but may
    be elsewhere in the file depending on the exact syntax problem.
  
    The offending line appears to be:
  
      tasks:
      - debug:
        ^ here

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

[zaki@manager halloween]$ 
```

ので、`defined`を使って定義済みかどうかのチェックを入れてみる。  
(もっとスマートに書ける方法はあるかもしれないけど、ひとまずこれで動いた、という内容)

```yaml
---
- hosts: localhost
  tasks:
  - debug:
      msg: Happy Halloween
    when: (trick is defined and trick|bool) or (treat is defined and treat|bool)
```

結果

```
[zaki@manager halloween]$ ansible-playbook playbook.yml
 [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 [debug] *******************************************************************
skipping: [localhost]

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

未定義時は`false`と同等

```
[zaki@manager halloween]$ 
[zaki@manager halloween]$ ansible-playbook playbook.yml -e trick=True
 [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 [debug] *******************************************************************
ok: [localhost] => 
  msg: Happy Halloween

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

[zaki@manager halloween]$
[zaki@manager halloween]$
[zaki@manager halloween]$ ansible-playbook playbook.yml -e treat=True
 [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 [debug] *******************************************************************
ok: [localhost] => 
  msg: Happy Halloween

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

[zaki@manager halloween]$ 
```

`trick`か`treat`を`True`にすればOK


# 環境

```
[zaki@manager halloween]$ cat /etc/redhat-release 
CentOS Linux release 7.7.1908 (Core)
[zaki@manager halloween]$ 
[zaki@manager halloween]$ ansible-playbook --version
ansible-playbook 2.8.5
  config file = /home/zaki/work/ansible/halloween/ansible.cfg
  configured module search path = [u'/home/zaki/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
[zaki@manager halloween]$ 
[zaki@manager halloween]$ cat ansible.cfg 
[defaults]
stdout_callback = yaml
[zaki@manager halloween]$ 
```

# 余談(cowsay)

本当は牛に「trick or treat」って言わせたかったんだけど…

```
[zaki@manager halloween]$ sudo yum install cowsay

...

[zaki@manager halloween]$ ansible-playbook playbook.yml -e trick=True
 [WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'

 __________________
< PLAY [localhost] >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

 ________________________
< TASK [Gathering Facts] >
 ------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

ok: [localhost]
 ______________
< TASK [debug] >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

ok: [localhost] => 
  msg: Happy Halloween
 ____________
< PLAY RECAP >
 ------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[zaki@manager halloween]$ 
```

違う、そうじゃない。