1#!/usr/bin/env python 2 3# (c) 2015, Marc Abramowitz <marca@surveymonkey.com> 4# 5# This file is part of Ansible. 6# 7# Ansible is free software: you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation, either version 3 of the License, or 10# (at your option) any later version. 11# 12# Ansible is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 19 20# Dynamic inventory script which lets you use nodes discovered by Serf 21# (https://serfdom.io/). 22# 23# Requires the `serfclient` Python module from 24# https://pypi.org/project/serfclient/ 25# 26# Environment variables 27# --------------------- 28# - `SERF_RPC_ADDR` 29# - `SERF_RPC_AUTH` 30# 31# These variables are described at https://www.serfdom.io/docs/commands/members.html#_rpc_addr 32 33import argparse 34import collections 35import os 36import sys 37 38# https://pypi.org/project/serfclient/ 39from serfclient import SerfClient, EnvironmentConfig 40 41import json 42 43_key = 'serf' 44 45 46def _serf_client(): 47 env = EnvironmentConfig() 48 return SerfClient(host=env.host, port=env.port, rpc_auth=env.auth_key) 49 50 51def get_serf_members_data(): 52 return _serf_client().members().body['Members'] 53 54 55def get_nodes(data): 56 return [node['Name'] for node in data] 57 58 59def get_groups(data): 60 groups = collections.defaultdict(list) 61 62 for node in data: 63 for key, value in node['Tags'].items(): 64 groups[value].append(node['Name']) 65 66 return groups 67 68 69def get_meta(data): 70 meta = {'hostvars': {}} 71 for node in data: 72 meta['hostvars'][node['Name']] = node['Tags'] 73 return meta 74 75 76def print_list(): 77 data = get_serf_members_data() 78 nodes = get_nodes(data) 79 groups = get_groups(data) 80 meta = get_meta(data) 81 inventory_data = {_key: nodes, '_meta': meta} 82 inventory_data.update(groups) 83 print(json.dumps(inventory_data)) 84 85 86def print_host(host): 87 data = get_serf_members_data() 88 meta = get_meta(data) 89 print(json.dumps(meta['hostvars'][host])) 90 91 92def get_args(args_list): 93 parser = argparse.ArgumentParser( 94 description='ansible inventory script reading from serf cluster') 95 mutex_group = parser.add_mutually_exclusive_group(required=True) 96 help_list = 'list all hosts from serf cluster' 97 mutex_group.add_argument('--list', action='store_true', help=help_list) 98 help_host = 'display variables for a host' 99 mutex_group.add_argument('--host', help=help_host) 100 return parser.parse_args(args_list) 101 102 103def main(args_list): 104 args = get_args(args_list) 105 if args.list: 106 print_list() 107 if args.host: 108 print_host(args.host) 109 110 111if __name__ == '__main__': 112 main(sys.argv[1:]) 113