Source code for _roster.ansible
# -*- coding: utf-8 -*-
'''
Read in an Ansible inventory file or script
Flat inventory files should be in the regular ansible inventory format.
.. code-block:: ini
[servers]
salt.gtmanfred.com ansible_ssh_user=gtmanfred ansible_ssh_host=127.0.0.1 ansible_ssh_port=22 ansible_ssh_pass='password'
[desktop]
home ansible_ssh_user=gtmanfred ansible_ssh_host=12.34.56.78 ansible_ssh_port=23 ansible_ssh_pass='password'
[computers:children]
desktop
servers
[names:vars]
http_port=80
then salt-ssh can be used to hit any of them
.. code-block:: bash
[~]# salt-ssh -N all test.ping
salt.gtmanfred.com:
True
home:
True
[~]# salt-ssh -N desktop test.ping
home:
True
[~]# salt-ssh -N computers test.ping
salt.gtmanfred.com:
True
home:
True
[~]# salt-ssh salt.gtmanfred.com test.ping
salt.gtmanfred.com:
True
There is also the option of specifying a dynamic inventory, and generating it on the fly
.. code-block:: bash
#!/bin/bash
echo '{
"servers": [
"salt.gtmanfred.com"
],
"desktop": [
"home"
],
"computers": {
"hosts": [],
"children": [
"desktop",
"servers"
]
},
"_meta": {
"hostvars": {
"salt.gtmanfred.com": {
"ansible_ssh_user": "gtmanfred",
"ansible_ssh_host": "127.0.0.1",
"ansible_sudo_pass": "password",
"ansible_ssh_port": 22
},
"home": {
"ansible_ssh_user": "gtmanfred",
"ansible_ssh_host": "12.34.56.78",
"ansible_sudo_pass": "password",
"ansible_ssh_port": 23
}
}
}
}'
This is the format that an inventory script needs to output to work with ansible, and thus here.
.. code-block:: bash
[~]# salt-ssh --roster-file /etc/salt/hosts salt.gtmanfred.com test.ping
salt.gtmanfred.com:
True
Any of the [groups] or direct hostnames will return. The 'all' is special, and returns everything.
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import re
import copy
import json
import fnmatch
# Import Salt libs
import salt.utils
from salt.roster import get_roster_file
try:
from salt.utils.path import which as utils_which
from salt.utils.stringutils import to_str as utils_to_str
except ImportError:
from salt.utils import which as utils_which
from salt.utils import to_str as utils_to_str
CONVERSION = {
'ansible_ssh_host': 'host',
'ansible_ssh_port': 'port',
'ansible_ssh_user': 'user',
'ansible_ssh_pass': 'passwd',
'ansible_sudo_pass': 'sudo',
'ansible_ssh_private_key_file': 'priv',
}
__virtualname__ = 'ansible'
def __virtual__():
return (
utils_which('ansible-inventory') and __virtualname__,
'Install `ansible` to use inventory',
)
[docs]def targets(tgt, tgt_type='glob', **kwargs):
'''
Return the targets from the ansible inventory_file
Default: /etc/salt/roster
'''
inventory = __runner__['salt.cmd'](
'cmd.run', 'ansible-inventory -i {0} --list'.format(get_roster_file(__opts__))
)
__context__['inventory'] = json.loads(utils_to_str(inventory))
if tgt_type == 'glob':
hosts = [
host for host in _get_hosts_from_group('all') if fnmatch.fnmatch(host, tgt)
]
elif tgt_type == 'list':
hosts = [host for host in _get_hosts_from_group('all') if host in tgt]
elif tgt_type == 'pcre':
rgx = re.compile(tgt)
hosts = [host for host in _get_hosts_from_group('all') if rgx.search(host)]
elif tgt_type in ['grain', 'grain_pcre']:
grains = __runner__['cache.grains'](tgt, tgt_type=tgt_type)
hosts = list(grains.keys())
elif tgt_type in ['pillar', 'pillar_pcre']:
pillars = __runner__['cache.pillar'](tgt, tgt_type=tgt_type)
hosts = list(pillars.keys())
# elif tgt_type == 'compound':
# TODO: Implement the compound matcher, might need quite a bit of work,
# need to evaluate if it's worth pulling all this code from
# https://github.com/saltstack/salt/blob/develop/salt/matchers/compound_match.py
# or find a smarter way to achieve that.
elif tgt_type == 'nodegroup':
hosts = _get_hosts_from_group(tgt)
return {host: _get_hostvars(host) for host in hosts}
def _get_hosts_from_group(group):
inventory = __context__['inventory']
hosts = [host for host in inventory.get(group, {}).get('hosts', [])]
for child in inventory.get(group, {}).get('children', []):
hosts.extend(_get_hosts_from_group(child))
return hosts
def _get_hostvars(host):
hostvars = __context__['inventory']['_meta'].get('hostvars', {}).get(host, {})
ret = copy.deepcopy(__opts__.get('roster_defaults', {}))
for value in CONVERSION:
if value in hostvars:
ret[CONVERSION[value]] = hostvars.pop(value)
ret['minion_opts'] = hostvars
if 'host' not in ret:
ret['host'] = host
return ret