Ansible ist praktisch, nicht wahr? Wenn ich auf vielen Servern die gleiche Arbeit mache, denke ich, dass es Gott ist.
Es fühlt sich so an, als wäre es vollständig automatisiert, wenn man nur auf das Playbook trifft, aber ich wollte auch die Ausführung des Playbooks auf nette Weise automatisieren. Sie können ein Shell-Skript schreiben, aber das Parsen der Ergebnisse usw. ist problematisch.
Dieses Mal möchte ich Ansible von Python aus auf eine gute Art und Weise treffen. Ich konnte den Artikel nicht unerwartet finden.
Es ist leicht zu verstehen, wenn Sie aus __main__
lesen.
Ein Playbook, das ls -la /
auf 192.168.0.1
ausführt.
Wenn Sie Ansible in Befehlen verwendet haben, sollten Sie es leicht lesen können.
Bitte beachten Sie die einfachen Kommentare hier und da.
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-Entspricht dem Argument, das im Playbook angegeben werden kann
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
)
#Die Schlüsselauthentifizierung hat Priorität und wird nur verwendet, wenn das Kennwort abgefragt wird. Wenn Sie nicht schreiben möchten, ist es OK
passwords = dict(vault_pass='secret')
#Rückrufinstanziierung
results_callback = ResultCallback()
#Konvertieren Sie das Inventar in das 1-Liner-Format
sources = ','.join(host_list)
if len(host_list) == 1:
sources += ','
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=sources)
#Wert einstellen
variable_manager = VariableManager(loader=loader, inventory=inventory)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
#Lauf
tqm = None
try:
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
passwords=passwords,
stdout_callback=results_callback,
)
result = tqm.run(play)
finally:
#Temporäre Dateien nach dem Beenden löschen
if tqm is not None:
tqm.cleanup()
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
return results_callback
if __name__ == "__main__":
#Geben Sie den Ausführungshost an (auch im Inventar angegeben).
host_list = [ "[email protected]" ]
#Spielbuch definieren
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))
Sie können das Ausführungsergebniswörterbuch wie folgt abrufen. Das Folgende ist ein Auszug dessen, was von Json ausgegeben wurde.
{
"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
}
Die Ergebnisse sind auch in Python einfach zu verwenden, sodass sie leicht mit anderen Systemen kombiniert werden können. Ich habe nach dieser Methode gesucht, weil ich Ansible aus My Hobby Writing Python System aufrufen wollte. Es wäre großartig, wenn es für andere Menschen nützlich sein könnte.
Recommended Posts