blob: bb35e3fc7ea2de6c2dce33a576e23ca4c6be631a [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
11def usage_error(msg):
12 print >>sys.stderr, msg
13 sys.exit(posix.EX_USAGE)
14
15if len(sys.argv) == 1:
16 usage_error('Need to specify --list or --host.')
17
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)
25import reclass, config
26
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:
43 usage_error('nodes_uri not specified')
44
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
51# Invoke reclass according to what Ansible wants.
52# If the 'node' option is set, we want node information. If the option is
53# False instead, we print the inventory. Yeah for option abuse!
54if sys.argv[1] == '--list':
55 if len(sys.argv) > 2:
56 usage_error('Unknown arguments: ' + ' '.join(sys.argv[2:]))
57 options['node'] = False
58
59elif sys.argv[1] == '--host':
60 if len(sys.argv) < 3:
61 usage_error('Missing hostname.')
62 elif len(sys.argv) > 3:
63 usage_error('Unknown arguments: ' + ' '.join(sys.argv[3:]))
64 options['node'] = sys.argv[2]
65
66else:
67 usage_error('Unknown mode (--list or --host required).')
68
69data = reclass.get_data(options['storage_type'], options['nodes_uri'],
70 options['classes_uri'], options['node'])
71
72if options['node']:
73 # Massage and shift the data like Ansible wants it
74 data['parameters']['RECLASS'] = data['RECLASS']
75 for i in ('classes', 'applications'):
76 data['parameters']['RECLASS'][i] = data[i]
77 data = data['parameters']
78
79print reclass.output(data, options['output'], options['pretty_print'])
80
81sys.exit(posix.EX_OK)