Ansible界隈の人たちとの会話で何気なく「にゃんしぶる」という単語を使ったら、Ansible実行時にネコチャンが出てくるモジュールとか作りそうな流れになってきたので、ひとまずメッセージ出力でにゃんしぶるできないかどうか試してみましたにゃーん。。。
環境
[zaki@manager nyan]$ ansible --version
ansible 2.8.5
config file = /home/zaki/work/ansible/nyan/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
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 nyan]$
[zaki@manager nyan]$ cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
[zaki@manager nyan]$
なお、本記事の内容は、cowsay
の使い方・アレンジ方法と、Ansible Callback Pluginの簡単な作り方という構成になってます。
解説はいいからちょっと試したい
詳細は後述してるけど、/usr/local/bin/cowsay
に以下のスクリプトをコピペ。(スクリプトの引数を元に整形してascii artをprint
してるだけです)
#!/usr/bin/perl
my $border = "-" x ((length $ARGV[-1]) + 2);
print <<"__EOL__";
$border
< $ARGV[-1] >
$border
\\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
__EOL__
そしてchmod 755 /usr/local/bin/cowsay
で実行権限を付与して、Ansibleを実行すればOK
元に戻したくなったら、/usr/local/bin/cowsay
を削除すればOKです。
cowsay でにゃんしぶる
Ansible実行時に、システムにcowsay
コマンドがインストールされている場合、このコマンドを使ってtask名を出力する機能が備わっている。
Ansibleからcowsay
を呼び出している部分はこの箇所
自前の cowsay を用意してにゃんしぶる
Ansible実行時にcowsay
がインストールされているかどうかは、以下のリストに実行ファイルがあるかどうかを見て判断している。
b_COW_PATHS = (
b"/usr/bin/cowsay",
b"/usr/games/cowsay",
b"/usr/local/bin/cowsay", # BSD path for cowsay
b"/opt/local/bin/cowsay", # MacPorts path for cowsay
)
これらのパスのどこかに、実行可能なcowsay
スクリプト等を配置すればOK。
逆に言えば、Ansible実行時にパスが通っている場所(~/local/bin/cowsay
とか)にcowsay
を置いていても、これらのパス以外であれば反応しない。
なので、yum
などでcowsay
をインストールしなくても、/usr/local/bin/cowsay
を自分で用意してしまえば、Ansibleでにゃんしぶるが可能。
(※ chmod 755
で実行権限を与えるのをお忘れなく)
実装例
例えばPerlスクリプト
#!/usr/bin/perl
my $border = "-" x ((length $ARGV[-1]) + 2);
print <<"__EOL__";
$border
< $ARGV[-1] >
$border
\\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
__EOL__
オリジナルのcowsay
がインストール済みで、それ以外は特に追加設定を行わない場合、Ansibleからはcowsay -W 60 -f default "メッセージ"
という形式でcowsay
が実行される。
def banner_cowsay(self, msg, color=None):
if u": [" in msg:
msg = msg.replace(u"[", u"")
if msg.endswith(u"]"):
msg = msg[:-1]
runcmd = [self.b_cowsay, b"-W", b"60"]
if self.noncow:
thecow = self.noncow
if thecow == 'random':
thecow = random.choice(list(self.cows_available))
runcmd.append(b'-f')
runcmd.append(to_bytes(thecow))
runcmd.append(to_bytes(msg))
cmd = subprocess.Popen(runcmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = cmd.communicate()
self.display(u"%s\n" % to_text(out), color=color)
この関数の
runcmd = [self.b_cowsay, b"-W", b"60"]
[...]
runcmd.append(b'-f')
runcmd.append(to_bytes(thecow))
の部分。
なので、自作のcowsay
を作る場合は、この呼び出し仕様を踏まえて、引数の一番最後を取り出して出力すれば、にゃんしぶるが実行できる。
(Perlにおいてスクリプトの引数は@ARGV
配列で受け取ることができ、配列の末尾を参照するには配列インデックスに-1
を指定すれば取り出せる)
実行例
[zaki@manager nyan]$ 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] >
------------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
------------------------
< TASK [Gathering Facts] >
------------------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
ok: [localhost]
-------------
< TASK [ping] >
-------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
ok: [localhost]
------------
< PLAY RECAP >
------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[zaki@manager nyan]$
cowsay に自前のテンプレートを追加してにゃんしぶる
cowsay
自体はパッケージインストールし、cowsay
の出力テンプレートを用意することでもにゃんしぶるできる。
cowsay
はデフォルトで牛のAAでメッセージを表示するが、表示形式はいくつかサンプルがあり、オプションで表示を変えることができる。
女子エンジニアはcowsayで女子力をupさせよう - Qiita
cowsay の設定
[zaki@manager nyan]$ cowsay Ansible
_________
< Ansible >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
選択できるテンプレート
[zaki@manager nyan]$ cowsay -l
Cow files in /usr/share/cowsay:
beavis.zen blowfish bong bud-frogs bunny cheese cower default dragon
dragon-and-cow elephant elephant-in-snake eyes flaming-sheep ghostbusters
head-in hellokitty kiss kitty koala kosh luke-koala mech-and-cow meow milk
moofasa moose mutilated ren satanic sheep skeleton small sodomized
stegosaurus stimpy supermilker surgery telebears three-eyes turkey turtle
tux udder vader vader-koala www
[zaki@manager nyan]$
tux
を選んでみる
[zaki@manager nyan]$ cowsay -f tux Ansible
_________
< Ansible >
---------
\
\
.--.
|o_o |
|:_/ |
// \ \
(| | )
/'\_ _/`\
\___)=(___/
[zaki@manager nyan]$
じゃあこのテンプレートってどこにあるのかというと、リストの1行目Cow files in /usr/share/cowsay:
の通り、/usr/share/cowsay
以下にある。
[zaki@manager nyan]$ ls -F /usr/share/cowsay/
DragonAndCow.pm default.cow luke-koala.cow stimpy.cow
Example.pm dragon-and-cow.cow mech-and-cow.cow supermilker.cow
Frogs.pm dragon.cow meow.cow surgery.cow
MechAndCow.pm elephant-in-snake.cow milk.cow telebears.cow
Stegosaurus.pm elephant.cow moofasa.cow three-eyes.cow
TextBalloon.pm eyes.cow moose.cow turkey.cow
TuxStab.pm flaming-sheep.cow mutilated.cow turtle.cow
beavis.zen.cow ghostbusters.cow ren.cow tux.cow
blowfish.cow head-in.cow satanic.cow udder.cow
bong.cow hellokitty.cow sheep.cow vader-koala.cow
bud-frogs.cow kiss.cow skeleton.cow vader.cow
bunny.cow kitty.cow small.cow www.cow
cheese.cow koala.cow sodomized.cow
cower.cow kosh.cow stegosaurus.cow
中身はPerlスクリプトで、$the_cow
変数に出力するAAをセットしている。
##
## TuX
## (c) pborys@p-soft.silesia.linux.org.pl
##
$the_cow = <<EOC;
$thoughts
$thoughts
.--.
|o_o |
|:_/ |
// \\ \\
(| | )
/'\\_ _/`\\
\\___)=(___/
EOC
[zaki@manager nyan]$
ということは、あとはわかるな?
##
## A cow wadvertising the World Wide Web, from lim@csua.berkeley.edu
##
$the_cow = <<EOC;
\\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
EOC
ちなみに、日本語(多バイト文字)を含む場合、UTF-8では文字化けするため、UTF-16 LEで保存してある。
[zaki@manager ~]$ cowsay -l
Cow files in /usr/share/cowsay:
beavis.zen blowfish bong bud-frogs bunny cat cheese cower default dragon
dragon-and-cow elephant elephant-in-snake eyes flaming-sheep ghostbusters
head-in hellokitty kiss kitty koala kosh luke-koala mech-and-cow meow milk
moofasa moose mutilated ren satanic sheep skeleton small sodomized
stegosaurus stimpy supermilker surgery telebears three-eyes turkey turtle
tux udder vader vader-koala www
↑cat
が追加されている。
cat
を指定して実行。
[zaki@manager ~]$ cowsay -f cat Ansible
_________
< Ansible >
---------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
[zaki@manager ~]$
なお、パッケージで配置されるファイルの置き場である/usr/share/cowsay
に自前のファイルを紛れさせるのが宗教上の理由等により不可能な場合は、/usr/local/share/cowsay/cat.cow
に保存し、実行時に環境変数COWPATH
で指定しても動く。(詳細はmanかcowsay
のソース)
[zaki@manager ~]$ COWPATH=/usr/local/share/cowsay cowsay -l
Cow files in /usr/local/share/cowsay:
cat
[zaki@manager ~]$ COWPATH=/usr/local/share/cowsay cowsay -f cat aaa
_____
< aaa >
-----
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
[zaki@manager ~]$
複数パス設定
[zaki@manager ~]$ COWPATH=/usr/local/share/cowsay:/usr/share/cowsay cowsay -l
Cow files in /usr/local/share/cowsay:
cat
Cow files in /usr/share/cowsay:
beavis.zen blowfish bong bud-frogs bunny cheese cower default dragon
dragon-and-cow elephant elephant-in-snake eyes flaming-sheep ghostbusters
head-in hellokitty kiss kitty koala kosh luke-koala mech-and-cow meow milk
moofasa moose mutilated ren satanic sheep skeleton small sodomized
stegosaurus stimpy supermilker surgery telebears three-eyes turkey turtle
tux udder vader vader-koala www
[zaki@manager ~]$
Ansible の設定
cowsay
で自前のテンプレートでメッセージ出力する準備ができたので、Ansibleから指定のテンプレートを使う設定を行う。
といっても、ansible.cfg
に記述するだけ。
(自前のテンプレートが/usr/local/share/cowsay
などデフォルト以外にある場合はCOWPATH=/usr/local/share/cowsay
が必要)
[defaults]
cow_selection = cat
ちなみにここにtux
などの、cowsay -l
で表示されるリストの項目を記述すれば、その内容でAnsibleの出力が行われる。
また、random
にすれば、使用可能なテンプレートから出力のたびにランダムで一つ選ばれる。
実行例
[zaki@manager nyan]$ 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] >
------------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
________________________
< TASK [Gathering Facts] >
------------------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
ok: [localhost]
_____________
< TASK [ping] >
-------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
ok: [localhost]
____________
< PLAY RECAP >
------------
\ ∧_∧
.ミ,,・_・ミ
ヾ(,_uuノ
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[zaki@manager nyan]$
cowsay を無効にする
[defaults]
nocows = True
あるいはyum erase cowsay
で削除する。
callback plugin でにゃんしぶる
ここまでのcowsay
を使ったにゃんしぶるだと、play名やtask名を出力しているだけなので、正常時はかわいいネコチャン、エラー時は毛が逆立ったネコチャン、みたいなことはできない。
この辺りをイジる場合は、callback plugin(普段使う時も「デフォルトのエラー見づらいわー、あ、でもyamlのstdout_callback
使うと見やすくなるらしいで」ってアレ)を使えば可能。
「にゃんしぶる用のcallback pluginを自作」することになるが、「何も設定しないときに使用されるdefault
callback plugin」をベースに作れば、表示をイジる程度であれば、コピペで簡単にできる。
Ansibleのcallback pluginを使って突然の死(echo-sd)を表現する - Qiita
callback pluginはAnsible本体と同じくPython製。
CentOS7でepelからパッケージインストールしたansible 2.8の場合は/usr/lib/python2.7/site-packages/ansible/plugins/callback/*.py
にプラグインのソースがある。
にゃんしぶる callback plugin を作る
まずはベースとなるdefault.py
を、プレイブックのあるディレクトリにcallback_plugins
ディレクトリを作成し、その下へnyansible.py
という名前でコピーする。
[zaki@manager nyan]$ mkdir callback_plugins/
[zaki@manager nyan]$ cp /usr/lib/python2.7/site-packages/ansible/plugins/callba
ck/default.py callback_plugins/nyansible.py
[zaki@manager nyan]$ ll callback_plugins/
合計 20
-rw-r--r--. 1 zaki zaki 17488 11月 4 12:36 nyansible.py
[zaki@manager nyan]$
defaultをベースにした最も簡単なコピペコード
default callback pluginの、表示に部分のメッセージを変更してあげればOK.
ただし、日本語(多バイトコード)をそのまま書いてしまうと文字化けしてしまうので、対応が必要。
日本語対応
ERROR! Unexpected Exception, this is probably a bug: Non-ASCII character '\xce' in file /home/zaki/work/ansible/nyan/callback_plugins/nyansible.py on line 89, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details (nyansible.py, line 89)
スクリプト内に日本語を使用する場合、スクリプトの1行目(普段のPythonスクリプトでshebang(#!/usr/bin/env python3
とか書くアレ)が1行目にある場合は2行目)にエンコードを指定する。
UTF-8であれば
# -*- coding: utf-8 -*-
と書く。
[WARNING]: Failure using method (v2_runner_on_ok) in callback plugin
(<ansible.plugins.callback.nyansible.CallbackModule object at 0x7fda2cacc410>):
'ascii' codec can't decode byte 0xe0 in position 0: ordinal not in range(128)
また、日本語を使用する各箇所でUnicode指定を表すu" ... "
という記述が必要。(ok
やchanged
のメッセージ出力はu
がないため、付け加える)
self._display.display("fatal: [%s]: FAILED! => %s" ...
を
self._display.display(u"エラー: [%s]: FAILED! => %s" ...
と書く。
変更点サンプル
[zaki@manager nyan]$ diff -u /usr/lib/python2.7/site-packages/ansible/plugins/c
allback/default.py callback_plugins/nyansible.py
--- /usr/lib/python2.7/site-packages/ansible/plugins/callback/default.py 2019-09-13 06:12:55.000000000 +0900
+++ callback_plugins/nyansible.py 2019-11-04 12:59:50.520091324 +0900
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -48,7 +49,7 @@
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
- CALLBACK_NAME = 'default'
+ CALLBACK_NAME = 'nyansible'
def __init__(self):
@@ -86,11 +87,11 @@
else:
if delegated_vars:
- self._display.display("fatal: [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'],
+ self._display.display(u"Σ(;Φ ω Φ): [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'],
self._dump_results(result._result)),
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
else:
- self._display.display("fatal: [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)),
+ self._display.display(u"Σ(;Φ ω Φ): [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)),
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
if ignore_errors:
@@ -107,9 +108,9 @@
self._print_task_banner(result._task)
if delegated_vars:
- msg = "changed: [%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
+ msg = u"ฅ/ᐠ。ᆽ。ᐟ \: [%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
else:
- msg = "changed: [%s]" % result._host.get_name()
+ msg = u"ฅ/ᐠ。ᆽ。ᐟ \: [%s]" % result._host.get_name()
color = C.COLOR_CHANGED
else:
if not self.display_ok_hosts:
@@ -119,9 +120,9 @@
self._print_task_banner(result._task)
if delegated_vars:
- msg = "ok: [%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
+ msg = u"ฅ(^・ω・^ฅ): [%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
else:
- msg = "ok: [%s]" % result._host.get_name()
+ msg = u"ฅ(^・ω・^ฅ): [%s]" % result._host.get_name()
color = C.COLOR_OK
self._handle_warnings(result._result)
[zaki@manager nyan]$
実行例
---
- hosts: localhost
tasks:
- ping:
- shell: date
- yum:
name: ruby
[zaki@manager nyan]$ 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] *********************************************************
ฅ(^・ω・^ฅ): [localhost]
TASK [ping] ********************************************************************
ฅ(^・ω・^ฅ): [localhost]
TASK [shell] *******************************************************************
ฅ/ᐠ。ᆽ。ᐟ \: [localhost]
TASK [yum] *********************************************************************
Σ(;Φ ω Φ): [localhost]: FAILED! => {"changed": false, "changes": {"installed": ["ruby"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
[zaki@manager nyan]$
エラーが見やすいyamlプラグインを継承したにゃんしぶる
defaultプラグインでなく、エラー時のメッセージをyaml形式で出力してくれるyamlプラグインをベースに作ってみる。
yamlプラグインは/usr/lib/python2.7/site-packages/ansible/plugins/ca llback/yaml.py
にソースがある。ただしこのソースを見ても、okやchanged・fatalを出力しているコードがない。
じゃあどうなっているのかというと、Ansibleのcallback pluginはCallbackModule
クラスを作るようになっていて、yamlプラグインはdefaultプラグインを継承して作られている。
つまり、基本的な処理はすべてdefaultプラグインの処理をそのまま使用し、出力処理のみyaml.dump()
を使うような実装になっている。
if abridged_result:
dumped += '\n'
dumped += to_text(yaml.dump(abridged_result, allow_unicode=True, width=1000, Dumper=AnsibleDumper, default_flow_style=False))
というわけなので、yamlプラグインを継承し、ok/changed/fatalなどを出力する処理をオーバーライドするような実装にしてやればOK
yamlプラグインのクラスを継承したにゃんしぶる用CallbackModuleクラスを作成する
まずは自前の処理を何も実装していない、yamlプラグインをそのまま継承しただけのクラスを作成。
こんな感じ。
名前はnyaml
にしました。
# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
callback: nyaml
type: stdout
short_description: nyaml-ized Ansible screen output
'''
from ansible.plugins.callback.yaml import CallbackModule as CallbackModule_yaml
class CallbackModule(CallbackModule_yaml):
"""
nyansible and nyaml /ᐠ。ꞈ。ᐟ\
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
CALLBACK_NAME = 'yaml'
※ この時点でansible.cfg
にstdout_callback = nyaml
と書けば(ただのyamlプラグインと同じように)動く。
メッセージ出力処理を実装する
defaultプラグインのソースからメッセージ出力処理の関数を拝借してくる。
対象はv2_runner_on_ok()
やv2_runner_on_failed()
など。
これらの関数をまずはコピペして動かしてみる。
すると、いくつか定義が足りないとwarningが出力される。
TASK [Gathering Facts] ********************************************************* [WARNING]: Failure using method (v2_runner_on_ok) in callback plugin
(<ansible.plugins.callback.nyaml.CallbackModule object at 0x7fc66f796c50>):
global name 'TaskInclude' is not defined
TASK [ping] ********************************************************************
TASK [shell] *******************************************************************
TASK [yum] ********************************************************************* [WARNING]: Failure using method (v2_runner_on_failed) in callback plugin
(<ansible.plugins.callback.nyaml.CallbackModule object at 0x7fc66f796c50>):
global name 'C' is not defined
TaskInclude
やC
が無いと言われている。
ので、これをdefaultプラグインのソースからさらに拝借する。(基本的にこの作業の繰り返し)
というわけで、全体のソースはこんな感じ。
# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
callback: nyaml
type: stdout
short_description: nyaml-ized Ansible screen output
'''
from ansible.plugins.callback.yaml import CallbackModule as CallbackModule_yaml
from ansible import constants as C
from ansible.playbook.task_include import TaskInclude
from ansible.utils.color import colorize, hostcolor
class CallbackModule(CallbackModule_yaml):
"""
nyansible and nyaml /ᐠ。ꞈ。ᐟ\
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
CALLBACK_NAME = 'yaml'
def v2_runner_on_failed(self, result, ignore_errors=False):
delegated_vars = result._result.get('_ansible_delegated_vars', None)
self._clean_results(result._result, result._task.action)
if self._last_task_banner != result._task._uuid:
self._print_task_banner(result._task)
self._handle_exception(result._result, use_stderr=self.display_failed_stderr)
self._handle_warnings(result._result)
if result._task.loop and 'results' in result._result:
self._process_items(result)
else:
if delegated_vars:
self._display.display(u"Σ(;Φ ω Φ): [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'],
self._dump_results(result._result)),
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
else:
self._display.display(u"Σ(;Φ ω Φ): [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)),
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
if ignore_errors:
self._display.display("...ignoring", color=C.COLOR_SKIP)
def v2_runner_on_ok(self, result):
delegated_vars = result._result.get('_ansible_delegated_vars', None)
if isinstance(result._task, TaskInclude):
return
elif result._result.get('changed', False):
if self._last_task_banner != result._task._uuid:
self._print_task_banner(result._task)
if delegated_vars:
msg = u"ฅ/ᐠ。ᆽ。ᐟ\: [%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
else:
msg = u"ฅ/ᐠ。ᆽ。ᐟ\: [%s]" % result._host.get_name()
color = C.COLOR_CHANGED
else:
if not self.display_ok_hosts:
return
if self._last_task_banner != result._task._uuid:
self._print_task_banner(result._task)
if delegated_vars:
msg = u"ฅ(^・ω・^ฅ): [%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
else:
msg = u"ฅ(^・ω・^ฅ): [%s]" % result._host.get_name()
color = C.COLOR_OK
self._handle_warnings(result._result)
if result._task.loop and 'results' in result._result:
self._process_items(result)
else:
self._clean_results(result._result, result._task.action)
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and '_ansible_verbose_override' not in result._result:
msg += " => %s" % (self._dump_results(result._result),)
self._display.display(msg, color=color)
nyamlプラグインでにゃんしぶる
このnyamlプラグインを使ってansible-playbook
を実行すると
[zaki@manager nyan]$ 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] *********************************************************
ฅ(^・ω・^ฅ): [localhost]
TASK [ping] ********************************************************************
ฅ(^・ω・^ฅ): [localhost]
TASK [shell] *******************************************************************
ฅ/ᐠ。ᆽ。ᐟ\: [localhost]
TASK [yum] *********************************************************************
Σ(;Φ ω Φ): [localhost]: FAILED! => changed=false
changes:
installed:
- ruby
msg: |-
You need to be root to perform this command.
rc: 1
results:
- |-
Loaded plugins: fastestmirror
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
[zaki@manager nyan]$
参考資料
ちなみに筆者はアイコンからもわかるかと思いますが、うさぎが好きです🐰