Ansible cowsay: Die sprechende Kuh, oder auch mehr Getier oder doch nur puristisch mit dem Ansible Stdout Compact Logger?
cowsay
Dass Admins zuweilen einen besonderen Humor haben und sich an doch sonderlichen Dingen erfreuen können, hat auch beim Thema Ansible seinen Platz gefunden: cowsay, die sprechende Kuh.
Der ein oder andere wird sich nun vielleicht fragen: Was? Noch nie davon gehört, noch nie gesehen!
Nun, die Ausgabe bei einem Ansible-Playbook lauf kennen wir ja nun schon zu genüge, die Ausgabe hier ist altbekannt:
$ ansible-playbook ~/ansible/playbooks/ssh_client_config.yml
PLAY [ssh_client_config.yml] ****************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************ ok: [localhost] TASK [ssh_client : include_tasks] ************************************************************************************************* included: /home/django/ansible/roles/ssh_client/tasks/client_config.yml for localhost TASK [ssh_client : Generieren und kopieren der SSH Client Konfiguration ~/.ssh/config.] ******************************************* ok: [localhost] PLAY RECAP ************************************************************************************************************************* localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Lassen wir es doch mal von der Kuh erklären, dann sieht so was schon anders aus.
______________________________ < PLAY [ssh_client_config.yml] > ------------------------------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ________________________ < TASK [Gathering Facts] > ------------------------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ok: [localhost] ___________________________________ < TASK [ssh_client : include_tasks] > ----------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || included: /home/django/ansible/roles/ssh_client/tasks/client_config.yml for localhost ___________________________________________________________ / TASK [ssh_client : Generieren und kopieren der SSH Client \ \ Konfiguration ~/.ssh/config.] / ----------------------------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ok: [localhost] ____________ < PLAY RECAP > ------------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || PLAY RECAP ************************************************************************************************************************* localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Installation
Wie kommt man nun zu dieser netten und spassigen Kuh. Nun ganz einfach, wie installieren einfach das Paket cowsay.
- Arch :
$ pacman -S cowsay
- Fedora / RHEL :
# yum install cowsay
bzw.
# dnf install cowsay
- Gentoo :
# emerge -av cowsay
- openSUSE :
$ sudo zypper in cowsay
- Ubuntu / Debian :
$ sudo apt-get install cowsay
Dokumentation
Wie es sich natürlich für jedes richtige Programm gehört, verfügt cowsay
selbstverständlich auch über eine entsprechende man-page!
$ man cowsay
COWSAY(6) Games Manual COWSAY(6)
NAME
cowsay/cowthink - configurable speaking/thinking cow (and a bit more)
SYNOPSIS
cowsay [-e eye_string] [-f cowfile] [-h] [-l] [-n] [-T tongue_string] [-W column] [-bdgpstwy]
DESCRIPTION
Cowsay generates an ASCII picture of a cow saying something provided by the user. If run with no arguments, it accepts
standard input, word-wraps the message given at about 40 columns, and prints the cow saying the given message on stan‐
dard output.
To aid in the use of arbitrary messages with arbitrary whitespace, use the -n option. If it is specified, the given
message will not be word-wrapped. This is possibly useful if you want to make the cow think or speak in figlet(6). If
-n is specified, there must not be any command-line arguments left after all the switches have been processed.
The -W specifies roughly where the message should be wrapped. The default is equivalent to -W 40 i.e. wrap words at or
before the 40th column.
If any command-line arguments are left over after all switches have been processed, they become the cow's message. The
program will not accept standard input for a message in this case.
There are several provided modes which change the appearance of the cow depending on its particular emotional/physical
state. The -b option initiates Borg mode; -d causes the cow to appear dead; -g invokes greedy mode; -p causes a state
of paranoia to come over the cow; -s makes the cow appear thoroughly stoned; -t yields a tired cow; -w is somewhat the
opposite of -t, and initiates wired mode; -y brings on the cow's youthful appearance.
The user may specify the -e option to select the appearance of the cow's eyes, in which case the first two characters
of the argument string eye_string will be used. The default eyes are 'oo'. The tongue is similarly configurable
through -T and tongue_string; it must be two characters and does not appear by default. However, it does appear in the
'dead' and 'stoned' modes. Any configuration done by -e and -T will be lost if one of the provided modes is used.
The -f option specifies a particular cow picture file (``cowfile'') to use. If the cowfile spec contains '/' then it
will be interpreted as a path relative to the current directory. Otherwise, cowsay will search the path specified in
the COWPATH environment variable. To list all cowfiles on the current COWPATH, invoke cowsay with the -l switch.
If the program is invoked as cowthink then the cow will think its message instead of saying it.
COWFILE FORMAT
A cowfile is made up of a simple block of perl(1) code, which assigns a picture of a cow to the variable $the_cow.
Should you wish to customize the eyes or the tongue of the cow, then the variables $eyes and $tongue may be used. The
trail leading up to the cow's message balloon is composed of the character(s) in the $thoughts variable. Any back‐
slashes must be reduplicated to prevent interpolation. The name of a cowfile should end with .cow, otherwise it is as‐
sumed not to be a cowfile. Also, at-signs (``@'') must be backslashed because that is what Perl 5 expects.
COMPATIBILITY WITH OLDER VERSIONS
What older versions? :-)
Version 3.x is fully backward-compatible with 2.x versions. If you're still using a 1.x version, consider upgrading.
And tell me where you got the older versions, since I didn't exactly put them up for world-wide access.
Oh, just so you know, this manual page documents version 3.03 of cowsay.
ENVIRONMENT
The COWPATH environment variable, if present, will be used to search for cowfiles. It contains a colon-separated list
of directories, much like PATH or MANPATH. It should always contain the /usr/share/cowsay/cows directory, or at least
a directory with a file called default.cow in it.
FILES
/usr/share/cowsay/cows holds a sample set of cowfiles. If your COWPATH is not explicitly set, it automatically con‐
tains this directory.
BUGS
If there are any, please notify the author at the address below.
AUTHOR
Tony Monroe (tony@nog.net), with suggestions from Shannon Appel (appel@CSUA.Berkeley.EDU) and contributions from An‐
thony Polito (aspolito@CSUA.Berkeley.EDU).
SEE ALSO
perl(1), wall(1), nwrite(1), figlet(6)
$Date: 1999/11/04 19:50:40 $ COWSAY(6)
Ausgabe
Steuerung
Will man keine Kuh mehr sehen, dann kann man diese temporär durch Nutzung der Option ANSIBLE_NOCOWS=1 beim Aufruf eines Playbook unterdrücken.
$ ANSIBLE_NOCOWS=1 ansible-playbook playbooks/ssh_client_config.yml
Dauerhaft kann man natürlich das Paket wieder deinstallieren bzw. in der Ansible-Konfigurationsdatei den Parameter nocows = True
setzen.
$ vim ~/.ansible.cfg
- ~/.ansible.cfg
... [defaults] nocows = True ...
Alternative Ausgaben
Ist man der Kuh überdrüssig, kann man sich auch einiges anderes Getier auf den Bildschirm holen. Was es alles gibt findet man mit dem Befehl cowsay -l
heraus.
$ cowsay -l
Cow files in /usr/share/cowsay/cows: apt bud-frogs bunny calvin cheese cock cower daemon default dragon dragon-and-cow duck elephant elephant-in-snake eyes flaming-sheep fox ghostbusters gnu hellokitty kangaroo kiss koala kosh luke-koala mech-and-cow milk moofasa moose pony pony-smaller ren sheep skeleton snowman stegosaurus stimpy suse three-eyes turkey turtle tux unipony unipony-smaller vader vader-koala www
Der SUSE-Enthusiast wird sich vermutlich an der Option suse erfreuen:
________________________ < TASK [Gathering Facts] > ------------------------ \ \____ /@ ~-. \/ __ .- | // // @
Auch der Kandidat hier, ist sicherlich den allermeisten wohl bekannt…
___________________________________________________________ / TASK [ssh_client : Generieren und kopieren der SSH Client \ \ Konfiguration ~/.ssh/config.] / ----------------------------------------------------------- \ \ ."'=-, ,.,.,_ (_____ )."=` `"=, ./_ _ \`\ `;.. / (o(o) |\=\ ; `; (_/| | \ | ;`"` | | ` ; \ .. /`,_ _.' `---' `#"#""'"#'#^ # # # # # # # # # # # # /#|#\ /#|#\ ok: [localhost]
… und mein ganz persönlicher Favorit:
______________________________ < PLAY [ssh_client_config.yml] > ------------------------------ \ \ ,=""=, c , _,{ /\ @ ) __ / ^~~^\ <=.,__/ '}= (_/ ,, ,,) \_ _>_/~ ~\_(/-\)'-,_,_,_,-'(_)-(_)
Ansible Stdout Compact Logger
Natürlich gibt es auch etwas für die Puristen und ernsthaft arbeitenden Administratoren. Die Standardausgabe von Ansible kennen wir bereits:
✔ ~/ansible [main✔] 15:26 $ ansible-playbook playbooks/ssh_client_config.yml
PLAY [ssh_client_config.yml] ***************************************************************************************** TASK [Gathering Facts] *********************************************************************************************** ok: [localhost] TASK [ssh_client : include_tasks] ************************************************************************************ included: /home/django/ansible/roles/ssh_client/tasks/config.yml for localhost TASK [ssh_client : Generieren und kopieren der SSH Client Konfiguration ~/.ssh/config.] ****************************** changed: [localhost] TASK [ssh_client : include_tasks] ************************************************************************************ included: /home/django/ansible/roles/ssh_client/tasks/known_hosts.yml for localhost TASK [ssh_client : Generieren und kopieren der /etc/ssh/ssh_known_hosts.] ******************************************** ok: [localhost] PLAY RECAP *********************************************************************************************************** localhost : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Besonders bei doch sehr umfangreichen Playbooks wünscht man sich dann doch eine stark gestraffte Ausgabe, wie z.B. die das nachfolgende Beispiel zeigt.
✔ ~/ansible [main✔] 17:43 $ ansible-playbook playbooks/ssh_client_config.yml
[17:43:22] Gathering Facts ↳ localhost | SUCCESS | 1.73s [17:43:24] ssh_client : include_tasks ↳ localhost | SUCCESS | 6ms [17:43:24] ↳ config: Generieren und kopieren der SSH Client Konfiguration ~/.ssh/config. ↳ localhost | CHANGED | 1.64s [17:43:26] ssh_client : include_tasks ↳ localhost | SUCCESS | 5ms [17:43:26] ↳ known_hosts: Generieren und kopieren der /etc/ssh/ssh_known_hosts. ↳ localhost | SUCCESS | 521ms [17:43:26] system -- Play recap -- localhost : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Für dieses kompakte Ausgabeformat nutzt man den Ansible Stdout Compact Logger.
Installation
Die Installation ist relativ schnell erledigt, da wir uns hierzu lediglich das Python-Script von der GitHub-Seite herunterladen und im Verzeichnis ~/.ansible/plugins/callback
ablegen müssen.
Legen wir uns als erstes das betreffende Unterverzeichnis an.
$ mkdir -p ~/.ansible/plugins/callback
Anschließend holen wir uns das Python-Script und speicher es direkt in gerade angelegten Plugin-Verzeichnis unserer Ansible-Installation.
$ curl https://raw.githubusercontent.com/octplane/ansible_stdout_compact_logger/main/callbacks/anstomlog.py \ -o ~/.ansible/plugins/callback/anstomlog.py
Konfiguration
Die Konfiguration für die kompakte Ausgabe des Ansible Stdout Compact Logger nehmen wir in der lokalen Userbezognen AnsibleKonfigurationsdatei ~/.ansible.cfg
vor. Hier aktivieren wir die beiden Einträge stdout_callback=anstomlog
sowie callback_plugins = ~/.ansible/plugins/callback
.
$ vim ~/.ansible.cfg
... # change the default callback, you can only have one 'stdout' type enabled at a time. #stdout_callback = skippy stdout_callback=anstomlog ... ... # set plugin path directories here, separate with colons #action_plugins = /usr/share/ansible/plugins/action #become_plugins = /usr/share/ansible/plugins/become #cache_plugins = /usr/share/ansible/plugins/cache #callback_plugins = /usr/share/ansible/plugins/callback callback_plugins = ~/.ansible/plugins/callback #connection_plugins = /usr/share/ansible/plugins/connection #lookup_plugins = /usr/share/ansible/plugins/lookup #inventory_plugins = /usr/share/ansible/plugins/inventory #vars_plugins = /usr/share/ansible/plugins/vars #filter_plugins = /usr/share/ansible/plugins/filter #test_plugins = /usr/share/ansible/plugins/test #terminal_plugins = /usr/share/ansible/plugins/terminal #strategy_plugins = /usr/share/ansible/plugins/strategy ...
Zum Schluss können wir uns noch vergewissern, ob die Installation und Konfiguration auch erfolgreich war. Hierzu rufen wir das Pythonscript anstomlog.py
ohne weitere Parameter direkt auf.
$ python3 ~/.ansible/plugins/callback/anstomlog.py
............ ---------------------------------------------------------------------- Ran 12 tests in 0.000s OK
Ausgabe
Rufen wir nun ein doch etwas umfangreicheres Playbook auf, haben wir nun eine kompakte Zusammenfassung aller relevanten Vorgänge und kein doch eher aufgeblähtes Ausgabe mit vielen ***- und Leer-Zeilen.
✔ ~/ansible [main✔] 18:23 $ ansible-playbook playbooks/kvm_arch_iso.yml
[18:23:34] ↳ arch_iso: Keyring orgdnungsgemäß initialisieren.
↳ vml000202 | SUCCESS | 1.12s
[18:23:35] ↳ arch_iso: Default Schlüssel neu laden.
↳ vml000202 | SUCCESS | 4.44s
[18:23:39] ↳ arch_iso: System aktualisieren.
↳ vml000202 | SUCCESS | 1.38s
[18:23:41] ↳ arch_iso: ggf. vorhandene Altlasten beseitigen.
↳ vml000202 | CHANGED | 6.09s
[18:23:47] ↳ arch_iso: Installation des Paketes archiso.
↳ vml000202 | SUCCESS | 2.24s
[18:23:49] ↳ arch_iso: Verzeichnis releng kopieren.
↳ vml000202 | SUCCESS | 497ms
[18:23:50] ↳ arch_iso: Verzeichnis für den systemd autostart des sshd anlegen.
↳ vml000202 | SUCCESS | 484ms
[18:23:50] ↳ arch_iso: symbolic-link für den Autostart des SSHD setzen.
↳ vml000202 | SUCCESS | 500ms
[18:23:51] ↳ arch_iso: Tage berechnen die seit dem 01.01.1970 vergangen sind.
↳ vml000202 | SUCCESS | 523ms
[18:23:51] ↳ arch_iso: Ergebnis in einer Variable zur weiteren Bearbeitung vorhalten.
↳ vml000202 | SUCCESS | 31ms
[18:23:51] ↳ arch_iso: Root-Passwort in der /etc/shadow Datei ablegen.
↳ vml000202 | CHANGED | 1.10s
[18:23:52] ↳ arch_iso: Verzeichnis für den ssh-key beim User Root anlegen.
↳ vml000202 | CHANGED | 537ms
[18:23:53] ↳ arch_iso: SSH-Key für den Zugriff für root hinterlegen.
↳ vml000202 | CHANGED | 917ms
[18:23:54] ↳ arch_iso: Autologin des Users root deaktivieren.
↳ vml000202 | SUCCESS | 518ms
[18:23:54] ↳ arch_iso: broadcom-wl aus der zu installierenden Pakete löschen.
↳ vml000202 | CHANGED | 576ms
[18:23:55] ↳ arch_iso: ISO erstellen.
↳ vml000202 | SUCCESS | 8m12s
[18:32:07] ↳ arch_iso: Installation des Paketes apache.
↳ vml000202 | SUCCESS | 2.13s
[18:32:09] ↳ arch_iso: http.conf anpassen.
↳ vml000202 | SUCCESS | 997ms
[18:32:10] ↳ arch_iso: Sicherstellen, dass der HTTP-Daemon startet.
↳ vml000202 | SUCCESS | 942ms
[18:32:11] ↳ arch_iso: Datum ermitteln.
↳ vml000202 | SUCCESS | 466ms
[18:32:12] ↳ arch_iso: Ergebnis in einer Variable zur weiteren Bearbeitung vorhalten.
↳ vml000202 | SUCCESS | 24ms
[18:32:12] ↳ arch_iso: ISO auf dem KVM-Wirt I holen.
↳ vml000202 -> kvm | CHANGED | 17.35s
[18:32:29] ↳ arch_iso: ISO auf dem KVM-Wirt II holen.
vml000202 | UNREACHABLE!: Failed to connect to the host via ssh: django@pml010102.intra.nausch.org: Permission denied (publickey,password).
[18:32:29] system
-- Play recap --
vml000202 : ok=22 changed=6 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
Ohne die kompakte Ausgabe mit Hilfe des Ansible Stdout Compact Logger würde die Ausgabe des obigen Beispiels mehrere Bildschirmseiten füllen!
Fazit und Ausblick
O.K., cowsay
- warum gibt es das überhaupt?
Warum nicht? cowsay
ist ein bisschen Spass in einer Umgebung, die normalerweise ziemlich „trocken“ und langweilig ist. Die Option ANSIBLE_COW_SELECTION=random
bringt wie der Namen schon sagt, zufällige ASCII-Geschöpfe auf den Bildschirm - Langeweile kommt so nicht auf - O.K. beim Ausmachen eines grossen Mehrwerts wird man sich vermutlich auch schwer tun. Aber ein wenig Spass muss auch ab und an sein, oder?
Natürlich wird man bei grossen und umfangreichen Orchestrierungsaufgaben eher auf die Verwendung des Ansible Stdout Compact Logger
zurück greifen. Hat man so doch schneller einen Überblick über den kompletten Anlauf einer Orchestrierungsaufgabe - Spass hin oder her, aber im Zweifels- und Debugging-Fall ist in aller Regel doch eher schnell Schluss mit lustig!