Ansible est pratique, n'est-ce pas? Quand je fais le même travail sur de nombreux serveurs, je pense que c'est Dieu.
On a l'impression que c'est entièrement automatisé simplement en accédant au playbook, mais je voulais aussi automatiser l'exécution du playbook d'une manière agréable. Vous pouvez écrire un script shell, mais l'analyse des résultats, etc. est problématique.
Donc, cette fois, je voudrais frapper Ansible de Python dans le bon sens. Je n'ai pas pu trouver l'article de manière inattendue.
Il est facile de comprendre si vous lisez depuis __main__
.
Un playbook qui exécute ls -la /
sur 192.168.0.1
.
Si vous avez utilisé Ansible dans les commandes, vous devriez pouvoir le lire facilement.
Veuillez vous référer aux simples commentaires ici et là.
pip3 install ansible
import json
import shutil
from ansible.module_utils.common.collections import ImmutableDict
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
from ansible import context
import ansible.constants as C
class ResultCallback(CallbackBase):
def __init__(self, *args, **kwargs):
super(ResultCallback, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {}
def v2_runner_on_unreachable(self, result):
host = result._host
self.host_unreachable[host.get_name()] = result
def v2_runner_on_ok(self, result, *args, **kwargs):
host = result._host
self.host_ok[host.get_name()] = result
def v2_runner_on_failed(self, result, *args, **kwargs):
host = result._host
self.host_failed[host.get_name()] = result
def ansible_run(play_source, host_list):
# ansible-Identique à l'argument qui peut être spécifié dans le playbook
context.CLIARGS = ImmutableDict(
tags={},
listtags=False,
listtasks=False,
listhosts=False,
syntax=False,
connection='ssh',
module_path=None,
forks=100,
private_key_file=None,
ssh_common_args=None,
ssh_extra_args=None,
sftp_extra_args=None,
scp_extra_args=None,
become=False,
become_method='Sudo',
become_user='root',
verbosity=True,
check=False,
start_at_task=None
)
#La priorité est donnée à l'authentification par clé et elle n'est utilisée que lorsque le mot de passe est demandé. Si tu ne veux pas écrire, c'est OK
passwords = dict(vault_pass='secret')
#Instanciation de rappel
results_callback = ResultCallback()
#Convertir l'inventaire au format 1 ligne
sources = ','.join(host_list)
if len(host_list) == 1:
sources += ','
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=sources)
#Définir la valeur
variable_manager = VariableManager(loader=loader, inventory=inventory)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
#Courir
tqm = None
try:
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
passwords=passwords,
stdout_callback=results_callback,
)
result = tqm.run(play)
finally:
#Suppression des fichiers temporaires après avoir quitté
if tqm is not None:
tqm.cleanup()
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
return results_callback
if __name__ == "__main__":
#Spécifiez l'hôte d'exécution (également spécifié dans l'inventaire)
host_list = [ "[email protected]" ]
#Définir le playbook
play_source = dict(
name = "Ansible Play",
hosts = host_list,
gather_facts = 'no',
tasks = [
dict(action=dict(module='shell', args='ls -l /'), register='shell_out')
]
)
results = ansible_run(play_source=play_source, host_list=host_list)
for host, result in results.host_ok.items():
print(host)
print(json.dumps(result._result, indent=4))
for host, result in results.host_failed.items():
print(host)
print(json.dumps(result._result, indent=4))
for host, result in results.host_unreachable.items():
print(host)
print(json.dumps(result._result, indent=4))
Vous pouvez obtenir le dictionnaire des résultats d'exécution comme ceci. Ce qui suit est un extrait de ce qui a été produit par Json.
{
"cmd": "ls -l /",
"stdout": "total 28\nlrwxrwxrwx. 1 root root 7 May 11 2019 bin -> usr/bin\ndr-xr-xr-x. 6 root root 4096 Nov 12 18:17 boot\ndrwxr-xr-x. 7 root root 65 Nov 17 00:41 data\ndrwxr-xr-x. 21 root root 3580 Nov 23 12:10 dev\ndrwxr-xr-x. 104 root root 8192 Nov 22 14:11 etc\ndrwxr-xr-x. 6 root root 4096 Nov 20 13:06 gvolume0\ndrwxr-xr-x. 3 root root 4096 Nov 17 00:47 gvolume1\ndrwxr-xr-x. 3 root root 19 Nov 10 01:24 home\nlrwxrwxrwx. 1 root root 7 May 11 2019 lib -> usr/lib\nlrwxrwxrwx. 1 root root 9 May 11 2019 lib64 -> usr/lib64\ndrwxr-xr-x. 2 root root 6 May 11 2019 media\ndrwxr-xr-x. 2 root root 6 May 11 2019 mnt\ndrwxr-xr-x. 2 root root 6 May 11 2019 opt\ndr-xr-xr-x. 1056 root root 0 Nov 22 14:04 proc\ndr-xr-x---. 4 root root 192 Nov 23 11:27 root\ndrwxr-xr-x. 32 root root 1100 Nov 22 14:46 run\nlrwxrwxrwx. 1 root root 8 May 11 2019 sbin -> usr/sbin\ndrwxr-xr-x. 2 root root 6 May 11 2019 srv\ndr-xr-xr-x. 13 root root 0 Nov 22 14:04 sys\ndrwxrwxrwt. 9 root root 212 Nov 23 22:51 tmp\ndrwxr-xr-x. 12 root root 144 Nov 10 01:22 usr\ndrwxr-xr-x. 21 root root 4096 Nov 10 01:28 var",
"stderr": "",
"rc": 0,
"start": "2020-11-23 22:51:11.787866",
"end": "2020-11-23 22:51:11.793951",
"delta": "0:00:00.006085",
"changed": true,
"invocation": {
"module_args": {
"_raw_params": "ls -l /",
"_uses_shell": true,
"warn": true,
"stdin_add_newline": true,
"strip_empty_ends": true,
"argv": null,
"chdir": null,
"executable": null,
"creates": null,
"removes": null,
"stdin": null
}
},
"stdout_lines": [
"total 28",
"lrwxrwxrwx. 1 root root 7 May 11 2019 bin -> usr/bin",
"dr-xr-xr-x. 6 root root 4096 Nov 12 18:17 boot",
"drwxr-xr-x. 7 root root 65 Nov 17 00:41 data",
"drwxr-xr-x. 21 root root 3580 Nov 23 12:10 dev",
"drwxr-xr-x. 104 root root 8192 Nov 22 14:11 etc",
"drwxr-xr-x. 6 root root 4096 Nov 20 13:06 gvolume0",
"drwxr-xr-x. 3 root root 4096 Nov 17 00:47 gvolume1",
"drwxr-xr-x. 3 root root 19 Nov 10 01:24 home",
"lrwxrwxrwx. 1 root root 7 May 11 2019 lib -> usr/lib",
"lrwxrwxrwx. 1 root root 9 May 11 2019 lib64 -> usr/lib64",
"drwxr-xr-x. 2 root root 6 May 11 2019 media",
"drwxr-xr-x. 2 root root 6 May 11 2019 mnt",
"drwxr-xr-x. 2 root root 6 May 11 2019 opt",
"dr-xr-xr-x. 1056 root root 0 Nov 22 14:04 proc",
"dr-xr-x---. 4 root root 192 Nov 23 11:27 root",
"drwxr-xr-x. 32 root root 1100 Nov 22 14:46 run",
"lrwxrwxrwx. 1 root root 8 May 11 2019 sbin -> usr/sbin",
"drwxr-xr-x. 2 root root 6 May 11 2019 srv",
"dr-xr-xr-x. 13 root root 0 Nov 22 14:04 sys",
"drwxrwxrwt. 9 root root 212 Nov 23 22:51 tmp",
"drwxr-xr-x. 12 root root 144 Nov 10 01:22 usr",
"drwxr-xr-x. 21 root root 4096 Nov 10 01:28 var"
],
"stderr_lines": [],
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"_ansible_no_log": false
}
Les résultats sont également faciles à utiliser en Python, il est donc facile de les combiner avec d'autres systèmes. Je cherchais cette méthode parce que je voulais frapper Ansible à partir du système Python que j'écris comme passe-temps. Ce serait formidable si cela pouvait être utile à d'autres personnes.
Recommended Posts