diff --git a/pyexecplugins/Ansible.py b/pyexecplugins/Ansible.py index 3a5c9d1..eb1f9ec 100644 --- a/pyexecplugins/Ansible.py +++ b/pyexecplugins/Ansible.py @@ -1,5 +1,6 @@ from pyexecplugins.pyexecplugins import PyExecPlugin import json +import sys, os, traceback import shutil import logging import ansible.constants as C @@ -57,17 +58,20 @@ class Ansible(PyExecPlugin): self.hosts = self.data.get("hosts", ["localhost"]) self.connection = self.data.get("connection","local") self.verbosity = self.data.get("verbosity", 0) - self.extra_vars = [self.data.get("extra_vars", None)] + self.extra_vars = [self.data.get("extra_vars")] if self.data.get("extra_vars") else [] self.gather_facts = self.data.get("gather_facts", False) + logging.getLogger("pyexec").debug("Hosts: %s\n Connection: %s\n Verbosity: %s\n Extra vars: %s\n Gather facts: %s\n", self.hosts, self.connection, self.verbosity, self.extra_vars, self.gather_facts) + def execute(self): # since the API is constructed for CLI it expects certain options to always be set in the context object context.CLIARGS = ImmutableDict(connection=self.connection, forks=10, become=False, become_method="sudo", become_user=None, check=False, diff=False, verbosity=self.verbosity, extra_vars = self.extra_vars) + # required for # https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/manager.py#L204 - if self.extra_vars[0].get("ansible_host"): + if (len(self.extra_vars) > 0) and self.extra_vars[0].get("ansible_host"): sources = self.extra_vars[0].get("ansible_host") else: sources = ','.join(self.hosts) @@ -75,6 +79,8 @@ class Ansible(PyExecPlugin): if len(self.hosts) == 1: sources += ',' + logging.getLogger("pyexec").debug("Sources are %s", sources) + # initialize needed objects loader = DataLoader() # Takes care of finding and reading yaml, json and ini files passwords = dict() @@ -86,11 +92,20 @@ class Ansible(PyExecPlugin): inventory = InventoryManager(loader=loader, sources=sources) # variable manager takes care of merging all the different sources to give you a unified view of variables available in each context - variable_manager = VariableManager(loader=loader, inventory=inventory) + logging.getLogger("pyexec").debug("Instiantiating VarableManager %s %s", loader, inventory) + try: + variable_manager = VariableManager(loader=loader, inventory=inventory) + except Exception as exc: + exc_type, exc_obj, exc_tb = sys.exc_info() + traceback.print_exc(file=sys.stdout) + fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] + logging.getLogger("pyexec").debug("%s %s %s", exc_type, fname, exc_tb.tb_lineno) + logging.getLogger("pyexec").error("%s", str(exc)) # instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks # IMPORTANT: This also adds library dirs paths to the module loader # IMPORTANT: and so it must be initialized before calling `Play.load()`. + logging.getLogger("pyexec").debug("Creating TaskQueueManager") tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, @@ -100,7 +115,9 @@ class Ansible(PyExecPlugin): ) # create data structure that represents our play + logging.getLogger("pyexec").debug("Loading playbook %s", self.playbook) play_sources = loader.load(self.playbook) + logging.getLogger("pyexec").debug("Play sources loaded %s", play_sources) for play_source in play_sources: logging.getLogger("pyexec").debug("Executing playsource: %s",play_source) play_source["gather_facts"] = self.gather_facts diff --git a/pyexecplugins/Packer.py b/pyexecplugins/Packer.py index 76df738..4efe485 100644 --- a/pyexecplugins/Packer.py +++ b/pyexecplugins/Packer.py @@ -1,7 +1,9 @@ from pyexecplugins.pyexecplugins import PyExecPlugin import tempfile import json +import logging import subprocess +from subprocess import PIPE class Plugin(PyExecPlugin): name = "Packer" @@ -21,10 +23,19 @@ class Plugin(PyExecPlugin): self.command = data.get("command", "build") def execute(self): - fp = tempfile.NamedTemporaryFile(mode="w", delete=False) - fp.write(json.dumps(self.template)) + fp = tempfile.NamedTemporaryFile(mode="w", delete=False, encoding='utf-8') + logging.getLogger("pyexec").debug("Going to %s template %s", self.command, self.data) + json.dump(self.template, fp) fp.close() - completed = subprocess.run(["packer", self.command, fp.name], capture_output=True, text=True) + cmd = ["packer", self.command, fp.name] + + try: + completed = subprocess.run(cmd, capture_output=True, text=True) + except Exception as e: + completed = subprocess.run(cmd, stdout=PIPE, stderr=PIPE) + + logging.getLogger("pyexec").debug("Packer outcome is %s", completed) + if(completed.returncode != 0): raise Exception("packer.io failed: {} - out:{} - err:{}".format( completed.returncode, @@ -35,8 +46,8 @@ class Plugin(PyExecPlugin): 'results' : [ { 'returncode' : completed.returncode, - 'stdout' : completed.stdout, - 'stderr': completed.stderr + 'stdout' : str(completed.stdout), + 'stderr': str(completed.stderr) } ] }