blob: 53b8f52d45462dd0dadf821a76751a645c90f497 [file] [log] [blame]
martin f. krafftf37f0682013-06-14 16:36:20 +02001#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# ansible-adapter — adapter between Ansible and reclass
5#
6# Copyright © 2007–13 martin f. krafft <madduck@madduck.net>
7# Released under the terms of the Artistic Licence 2.0
8#
9import os, sys, posix, stat
10
martin f. krafft3434b6b2013-06-14 20:40:52 +020011def exit_error(msg, rc):
martin f. krafftf37f0682013-06-14 16:36:20 +020012 print >>sys.stderr, msg
martin f. krafft3434b6b2013-06-14 20:40:52 +020013 sys.exit(rc)
martin f. krafftf37f0682013-06-14 16:36:20 +020014
15if len(sys.argv) == 1:
martin f. krafft3434b6b2013-06-14 20:40:52 +020016 exit_error('Need to specify --list or --host.', posix.EX_USAGE)
martin f. krafftf37f0682013-06-14 16:36:20 +020017
18ansible_dir = os.path.dirname(sys.argv[0])
19
20# In order to be able to use reclass as modules, manipulate the search path,
21# starting from the location of the adapter. Realpath will make sure that
22# symlinks are resolved.
23realpath = os.path.realpath(sys.argv[0] + '/../../')
24sys.path.insert(0, realpath)
martin f. krafft3434b6b2013-06-14 20:40:52 +020025import reclass, config, errors
martin f. krafftf37f0682013-06-14 16:36:20 +020026
27# The adapter resides in the Ansible directory, so let's look there for an
28# optional configuration file called reclass-config.yml.
29options = {'output':'json', 'pretty_print':True}
30config_path = os.path.join(ansible_dir, 'reclass-config.yml')
31if os.path.exists(config_path) and os.access(config_path, os.R_OK):
32 options.update(config.read_config_file(config_path))
33
34# Massage options into shape
35if 'storage_type' not in options:
36 options['storage_type'] = 'yaml_fs'
37
38if 'nodes_uri' not in options:
39 nodes_uri = os.path.join(ansible_dir, 'nodes')
40 if stat.S_ISDIR(os.stat(nodes_uri).st_mode):
41 options['nodes_uri'] = nodes_uri
42 else:
martin f. krafft3434b6b2013-06-14 20:40:52 +020043 exit_error('nodes_uri not specified', posix.EX_USAGE)
martin f. krafftf37f0682013-06-14 16:36:20 +020044
45if 'classes_uri' not in options:
46 classes_uri = os.path.join(ansible_dir, 'classes')
47 if not stat.S_ISDIR(os.stat(classes_uri).st_mode):
48 classes_uri = options['nodes_uri']
49 options['classes_uri'] = classes_uri
50
martin f. krafft9a9b0ac2013-06-21 21:24:18 +020051if 'applications_postfix' not in options:
52 options['applications_postfix'] = '_hosts'
53
martin f. krafftf37f0682013-06-14 16:36:20 +020054# Invoke reclass according to what Ansible wants.
55# If the 'node' option is set, we want node information. If the option is
56# False instead, we print the inventory. Yeah for option abuse!
57if sys.argv[1] == '--list':
58 if len(sys.argv) > 2:
martin f. krafft3434b6b2013-06-14 20:40:52 +020059 exit_error('Unknown arguments: ' + ' '.join(sys.argv[2:]),
60 posix.EX_USAGE)
martin f. krafftf37f0682013-06-14 16:36:20 +020061 options['node'] = False
62
63elif sys.argv[1] == '--host':
64 if len(sys.argv) < 3:
martin f. krafft3434b6b2013-06-14 20:40:52 +020065 exit_error('Missing hostname.', posix.EX_USAGE)
martin f. krafftf37f0682013-06-14 16:36:20 +020066 elif len(sys.argv) > 3:
martin f. krafft3434b6b2013-06-14 20:40:52 +020067 exit_error('Unknown arguments: ' + ' '.join(sys.argv[3:]),
68 posix.EX_USAGE)
martin f. krafftf37f0682013-06-14 16:36:20 +020069 options['node'] = sys.argv[2]
70
71else:
martin f. krafft3434b6b2013-06-14 20:40:52 +020072 exit_error('Unknown mode (--list or --host required).', posix.EX_USAGE)
martin f. krafftf37f0682013-06-14 16:36:20 +020073
martin f. krafft3434b6b2013-06-14 20:40:52 +020074try:
75 data = reclass.get_data(options['storage_type'], options['nodes_uri'],
martin f. krafft9a9b0ac2013-06-21 21:24:18 +020076 options['classes_uri'],
77 options['applications_postfix'], options['node'])
martin f. krafftf37f0682013-06-14 16:36:20 +020078
martin f. krafft3434b6b2013-06-14 20:40:52 +020079 if options['node']:
80 # Massage and shift the data like Ansible wants it
81 data['parameters']['RECLASS'] = data['RECLASS']
82 for i in ('classes', 'applications'):
83 data['parameters']['RECLASS'][i] = data[i]
84 data = data['parameters']
martin f. krafftf37f0682013-06-14 16:36:20 +020085
martin f. krafft3434b6b2013-06-14 20:40:52 +020086 print reclass.output(data, options['output'], options['pretty_print'])
martin f. krafftf37f0682013-06-14 16:36:20 +020087
martin f. krafft3434b6b2013-06-14 20:40:52 +020088 sys.exit(posix.EX_OK)
89
90except errors.ReclassException, e:
91 exit_error(e.message, e.rc)