Exemplo n.º 1
0
    def build_inventory(self):
        self.clear_caches()

        loader = DataLoader()

        # Ansible 2.2 and 2.3 specific fixes
        if ansible_version.startswith('2.2.') or ansible_version.startswith(
                '2.3.'):
            variable_manager = ansible.vars.VariableManager()
            variable_manager.extra_vars = load_extra_vars(
                loader=loader, options=EmptyOptions())

            inventory = ansible.inventory.Inventory(
                loader=loader,
                variable_manager=variable_manager,
                host_list=self.inventory_path.strpath)
            variable_manager.set_inventory(inventory)
        # Ansible 2.4+
        else:
            inventory = InventoryManager(loader=loader,
                                         sources=self.inventory_path.strpath)
            variable_manager = VariableManager(loader=loader,
                                               inventory=inventory)
            variable_manager.extra_vars = load_extra_vars(
                loader=loader, options=EmptyOptions())

        return inventory
Exemplo n.º 2
0
 def clear_caches(self):
     # Ansible 2.2 and 2.3 specific fixes
     if ansible_version.startswith('2.2.') or ansible_version.startswith(
             '2.3.'):
         # unfortunately we have to reset caches as these are kept as module state
         ansible.inventory.HOSTS_PATTERNS_CACHE.clear()
         ansible.vars.HOSTVARS_CACHE.clear()
     # Ansible 2.4+
     elif self.inventory is not None:
         self.inventory.clear_caches()
Exemplo n.º 3
0
 def run(self):
     try:
         output = self.output
         if isinstance(output, logging.Logger):
             output = None
         if ansible_version.startswith("1."):
             self.result.put((0, self.launch_playbook_v1(), output))
         elif ansible_version.startswith("2."):
             self.result.put((0, self.launch_playbook_v2(), output))
         else:
             display("ERROR: Unknown Ansible version.", output=self.output)
             self.result.put((0, (1, []), output))
     except errors.AnsibleError, e:
         display("ERROR: %s" % e, output=self.output)
         self.result.put((0, (1, []), output))
Exemplo n.º 4
0
 def run(self):
     try:
         output = self.output
         if isinstance(output, logging.Logger):
             output = None
         if ansible_version.startswith("1."):
             self.result.put((0, self.launch_playbook_v1(), output))
         elif ansible_version.startswith("2."):
             self.result.put((0, self.launch_playbook_v2(), output))
         else:
             display("ERROR: Unknown Ansible version.", output=self.output)
             self.result.put((0, (1, []), output))
     except errors.AnsibleError, e:
         display("ERROR: %s" % e, output=self.output)
         self.result.put((0, (1, []), output))
Exemplo n.º 5
0
 def run(self):
     try:
         if ansible_version.startswith("1."):
             self.results = self.launch_playbook_v1()
         else:
             self.results = self.launch_playbook_v2()
     except errors.AnsibleError, e:
         display("ERROR: %s" % e, output=self.output)
         self.results = (1, [])
Exemplo n.º 6
0
 def run(self):
     try:
         if ansible_version.startswith("1."):
             self.results = self.launch_playbook_v1()
         else:
             self.results = self.launch_playbook_v2()
     except errors.AnsibleError, e:
         display("ERROR: %s" % e, output=self.output)
         self.results = (1, [])
Exemplo n.º 7
0
    def __init__(
        self, servers,
        ignore_unreachable=False,
        ignore_errors=False,
        **runner_args
    ):
        """ Initializes the api.

        :servers:
            A list of servers or a string with space-delimited servers. The
            api instances will operate on these servers only. Servers which
            cannot be reached or whose use triggers an error are taken out
            of the list for the lifetime of the object.

            e.g: ['server1', 'server2'] or 'server' or 'server1 server2'.

        :ignore_unreachable:
            If true, unreachable servers will not trigger an exception. They
            are however still taken out of the list for the lifetime of the
            object.

        :ignore_errors:
            If true, errors on servers will not trigger an exception. Servers
            who trigger an error are still ignored for the lifteime of the
            object.

        :**runner_args:
            All remining keyword arguments are passed to the Ansible runner
            initializiation. A common option would be sudo:

            Api('myserver', sudo=True)

        """
        if isinstance(servers, basestring):
            self.servers = servers.split(u' ')
        else:
            self.servers = list(servers)

        # if the target is the local host but the transport is not set default
        # to transport = 'local' as it's usually what you want
        if 'transport' not in runner_args:
            if set(self.servers).issubset(set(('localhost', '127.0.0.1'))):
                runner_args['transport'] = 'local'

        # Ansible 1.9+ changed the way the API does sudo. To support old code
        # we automatically switch to the new scheme if we need to.
        if 'sudo' in runner_args and __version__.startswith('1.9.'):
            runner_args['become'] = runner_args.pop('sudo')

        self.runner_args = runner_args
        self._valid_return_codes = (0, )

        self.ignore_unreachable = ignore_unreachable
        self.ignore_errors = ignore_errors

        for runner in (ModuleRunner(m) for m in list_ansible_modules()):
            runner.hookup(self)
Exemplo n.º 8
0
def worker(pending_queue: multiprocessing.Queue,
           completed_queue: multiprocessing.Queue) -> None:
    """Extract the documentation from a plugin, place in completed queue.

    :param pending_queue: A queue with plugins to process
    :param completed_queue: The queue in which extracted documentation will be placed
    """
    # pylint: disable=import-outside-toplevel

    # load the fragment_loader _after_ the path is set
    from ansible.plugins.loader import fragment_loader

    while True:
        entry = pending_queue.get()
        if entry is None:
            break
        collection_name, checksum, plugin_path = entry

        try:
            if ansible_version.startswith("2.9"):
                (doc, examples, returndocs, metadata) = get_docstring(
                    filename=str(plugin_path),
                    fragment_loader=fragment_loader,
                )
            else:
                (doc, examples, returndocs, metadata) = get_docstring(
                    filename=str(plugin_path),
                    fragment_loader=fragment_loader,
                    collection_name=collection_name,
                )

        except Exception as exc:  # pylint: disable=broad-except
            err_message = f"{type(exc).__name__} (get_docstring): {str(exc)}"
            completed_queue.put(
                ("error", (checksum, plugin_path, err_message)))
            continue

        try:
            q_message = {
                "plugin": {
                    "doc": doc,
                    "examples": examples,
                    "returndocs": returndocs,
                    "metadata": metadata,
                },
                "timestamp": datetime.utcnow().isoformat(),
            }
            completed_queue.put(
                ("plugin", (checksum, json.dumps(q_message, default=str))))
        except JSONDecodeError as exc:
            err_message = f"{type(exc).__name__} (json_decode_doc): {str(exc)}"
            completed_queue.put(
                ("error", (checksum, plugin_path, err_message)))
Exemplo n.º 9
0
#
# Some parts of this code are taken from the Ansible code
# (c) 2012-2014, Michael DeHaan <*****@*****.**>
#

import sys
import time
import os
from multiprocessing import Process
import subprocess
import signal
import logging
from ansible import errors
from ansible import __version__ as ansible_version

if ansible_version.startswith("1."):
    import ansible.playbook
    import ansible.inventory
    import ansible.constants as C
    from ansible import utils

    from ansible_callbacks import banner, AggregateStats, PlaybookCallbacks, PlaybookRunnerCallbacks
else:
    from ansible.cli import CLI
    from ansible.parsing.dataloader import DataLoader
    from ansible.vars import VariableManager
    import ansible.inventory

    from ansible_executor_v2 import IMPlaybookExecutor

Exemplo n.º 10
0
from __future__ import (absolute_import, division, print_function)

__metaclass__ = type

from ansible import __version__
from ansible.errors import AnsibleError

if __version__.startswith('1'):
    raise AnsibleError(
        'Trellis no longer supports Ansible 1.x. Please upgrade to Ansible 2.x.'
    )

# These imports will produce Traceback in Ansible 1.x, so place after version check
from __main__ import cli
from ansible.compat.six import iteritems


class VarsModule(object):
    ''' Creates and modifies host variables '''
    def __init__(self, inventory):
        self.inventory = inventory
        self.inventory_basedir = inventory.basedir()
        self._options = cli.options if cli else None

    # Wrap salts and keys variables in {% raw %} to prevent jinja templating errors
    def wrap_salts_in_raw(self, host, hostvars):
        if 'vault_wordpress_sites' in hostvars:
            for name, site in hostvars['vault_wordpress_sites'].iteritems():
                for key, value in site['env'].iteritems():
                    if key.endswith(
                        ('_key', '_salt')) and not value.startswith(
Exemplo n.º 11
0
#
# Some parts of this code are taken from the Ansible code
# (c) 2012-2014, Michael DeHaan <*****@*****.**>
#

import sys
import time
import os
from multiprocessing import Process
import subprocess
import signal
import logging
from ansible import errors
from ansible import __version__ as ansible_version

if ansible_version.startswith("1."):
    import ansible.playbook
    import ansible.inventory
    import ansible.constants as C
    from ansible import utils

    from ansible_callbacks import banner, AggregateStats, PlaybookCallbacks, PlaybookRunnerCallbacks
else:
    from ansible.cli import CLI
    from ansible.parsing.dataloader import DataLoader
    from ansible.vars import VariableManager
    import ansible.inventory

    from ansible_executor_v2 import IMPlaybookExecutor

Exemplo n.º 12
0
        if self._play_context.become and self._play_context.become_method == 'dockerexec':
            exec_user = self._play_context.become_user
        else:
            exec_user = self.remote_user

        if exec_user is not None:
            local_cmd += ['-u', exec_user]

        # -i is needed to keep stdin open which allows pipelining to work
        local_cmd += ['-i', self._play_context.remote_addr] + cmd

        return local_cmd


# Ansible 2.2 specific fixes
if ansible_version.startswith('2.2.'):
    @staticmethod
    def _sanitize_version(version):
        return re.sub(b'[^0-9a-zA-Z\.]', b'', version)

    def _get_docker_version(self):
        cmd, cmd_output, err, returncode = self._old_docker_version()
        if returncode == 0:
            for line in cmd_output.split(b'\n'):
                if line.startswith(b'Server version:'):  # old docker versions
                    return self._sanitize_version(line.split()[2]).decode('utf-8')

        cmd, cmd_output, err, returncode = self._new_docker_version()
        if returncode:
            raise AnsibleError('Docker version check (%s) failed: %s' % (cmd, err))
Exemplo n.º 13
0
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible import __version__
from ansible.errors import AnsibleError

if __version__.startswith('1'):
    raise AnsibleError('Trellis no longer supports Ansible 1.x. Please upgrade to Ansible 2.x.')

# This import will produce Traceback in Ansible 1.x, so place after version check
from __main__ import cli


class VarsModule(object):
    ''' Creates and modifies host variables '''

    def __init__(self, inventory):
        self.inventory = inventory
        self.inventory_basedir = inventory.basedir()
        self._options = cli.options if cli else None

    # Wrap salts and keys variables in {% raw %} to prevent jinja templating errors
    def wrap_salts_in_raw(self, host, hostvars):
        if 'vault_grav_sites' in hostvars:
            for name, site in hostvars['vault_grav_sites'].iteritems():
                for key, value in site['env'].iteritems():
                    if key.endswith(('_key', '_salt')) and not value.startswith(('{% raw', '{%raw')):
                        hostvars['vault_grav_sites'][name]['env'][key] = ''.join(['{% raw %}', value, '{% endraw %}'])
            host.vars['vault_grav_sites'] = hostvars['vault_grav_sites']

    def cli_args_vault(self):
Exemplo n.º 14
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            dest=dict(required=True, aliases=['name', 'destfile']),
            state=dict(default='present', choices=['absent', 'present']),
            marker=dict(default='# {mark} ANSIBLE MANAGED BLOCK', type='str'),
            block=dict(default='', type='str', aliases=['content']),
            insertafter=dict(default=None),
            insertbefore=dict(default=None),
            create=dict(default=False, type='bool'),
            backup=dict(default=False, type='bool'),
            validate=dict(default=None, type='str'),
        ),
        mutually_exclusive=[['insertbefore', 'insertafter']],
        add_file_common_args=True,
        supports_check_mode=True
    )

    params = module.params
    dest = os.path.expanduser(params['dest'])
    if module.boolean(params.get('follow', None)):
        dest = os.path.realpath(dest)

    if os.path.isdir(dest):
        module.fail_json(rc=256,
                         msg='Destination %s is a directory !' % dest)

    if not os.path.exists(dest):
        if not module.boolean(params['create']):
            module.fail_json(rc=257,
                             msg='Destination %s does not exist !' % dest)
        original = None
        lines = []
    else:
        f = open(dest, 'rb')
        original = f.read()
        f.close()
        lines = original.splitlines()

    insertbefore = params['insertbefore']
    insertafter = params['insertafter']
    block = params['block']
    marker = params['marker']
    present = params['state'] == 'present'

    if insertbefore is None and insertafter is None:
        insertafter = 'EOF'

    if insertafter not in (None, 'EOF'):
        insertre = re.compile(insertafter)
    elif insertbefore not in (None, 'BOF'):
        insertre = re.compile(insertbefore)
    else:
        insertre = None

    marker0 = re.sub(r'{mark}', 'BEGIN', marker)
    marker1 = re.sub(r'{mark}', 'END', marker)
    if present and block:
        # Escape seqeuences like '\n' need to be handled in Ansible 1.x
        if __version__.startswith('1.'):
            block = re.sub('', block, '')
        blocklines = [marker0] + block.splitlines() + [marker1]
    else:
        blocklines = []

    n0 = n1 = None
    for i, line in enumerate(lines):
        if line.startswith(marker0):
            n0 = i
        if line.startswith(marker1):
            n1 = i

    if None in (n0, n1):
        n0 = None
        if insertre is not None:
            for i, line in enumerate(lines):
                if insertre.search(line):
                    n0 = i
            if n0 is None:
                n0 = len(lines)
            elif insertafter is not None:
                n0 += 1
        elif insertbefore is not None:
            n0 = 0           # insertbefore=BOF
        else:
            n0 = len(lines)  # insertafter=EOF
    elif n0 < n1:
        lines[n0:n1+1] = []
    else:
        lines[n1:n0+1] = []
        n0 = n1

    lines[n0:n0] = blocklines

    if lines:
        result = '\n'.join(lines)+'\n'
    else:
        result = ''
    if original == result:
        msg = ''
        changed = False
    elif original is None:
        msg = 'File created'
        changed = True
    elif not blocklines:
        msg = 'Block removed'
        changed = True
    else:
        msg = 'Block inserted'
        changed = True

    if changed and not module.check_mode:
        if module.boolean(params['backup']) and os.path.exists(dest):
            module.backup_local(dest)
        write_changes(module, result, dest)

    msg, changed = check_file_attrs(module, changed, msg)
    module.exit_json(changed=changed, msg=msg)
Exemplo n.º 15
0
# add current dir to import path
import sys
import os
sys.path.append(os.path.dirname(__file__))

# import the right plugin for the right ansible major version
from ansible import __version__ as ansible_version
if ansible_version.startswith('2.'):
    from ansible2_nested_dict import LookupModule
elif ansible_version.startswith('1.'):
    from ansible1_nested_dict import LookupModule
    for thedef in cls.body:
        assert isinstance(thedef, ast.Assign), thedef
        assert len(thedef.targets) == 1
        key = thedef.targets[0].id
        assert isinstance(thedef.value, ast.Str)
        data = AnsibleLoader(thedef.value.s, file_name=path).get_single_data()
        fragments[key] = data
    return fragments


# TODO: figure out how to make this not crazy hacky
target_pythonpath = os.path.join('target', 'ansible_collections')
for namespace in os.listdir(target_pythonpath):
    namespace_dir = os.path.join(target_pythonpath, namespace)
    for name in os.listdir(namespace_dir):
        if namespace == 'ansible' and name == 'base' and __version__.startswith(
                '2.9'):
            print('skipping ansible.base b/c not a thing in 2.9')
            continue
        fqcn = f'{namespace}.{name}'
        req_data.setdefault(fqcn, [])
        collection_dir = os.path.join(namespace_dir, name)
        top_content = os.listdir(collection_dir)

        collection_dir = os.path.join(target_pythonpath, namespace, name)
        for candidate in os.listdir(collection_dir):
            # no thanks to python2
            if ('requirement' in candidate) and ('txt' in candidate) and (
                    '2.7' not in candidate):
                with open(os.path.join(collection_dir, candidate), 'r') as f:
                    req_text = f.read()
                req_text = req_text.strip()