| #!/usr/bin/python | 
 | # -*- coding: utf-8 -*- | 
 | # | 
 | # ansible-adapter — adapter between Ansible and reclass | 
 | # | 
 | # Copyright © 2007–13 martin f. krafft <madduck@madduck.net> | 
 | # Released under the terms of the Artistic Licence 2.0 | 
 | # | 
 | import os, sys, posix, stat | 
 |  | 
 | def usage_error(msg): | 
 |     print >>sys.stderr, msg | 
 |     sys.exit(posix.EX_USAGE) | 
 |  | 
 | if len(sys.argv) == 1: | 
 |     usage_error('Need to specify --list or --host.') | 
 |  | 
 | ansible_dir = os.path.dirname(sys.argv[0]) | 
 |  | 
 | # In order to be able to use reclass as modules, manipulate the search path, | 
 | # starting from the location of the adapter. Realpath will make sure that | 
 | # symlinks are resolved. | 
 | realpath = os.path.realpath(sys.argv[0] + '/../../') | 
 | sys.path.insert(0, realpath) | 
 | import reclass, config | 
 |  | 
 | # The adapter resides in the Ansible directory, so let's look there for an | 
 | # optional configuration file called reclass-config.yml. | 
 | options = {'output':'json', 'pretty_print':True} | 
 | config_path = os.path.join(ansible_dir, 'reclass-config.yml') | 
 | if os.path.exists(config_path) and os.access(config_path, os.R_OK): | 
 |     options.update(config.read_config_file(config_path)) | 
 |  | 
 | # Massage options into shape | 
 | if 'storage_type' not in options: | 
 |     options['storage_type'] = 'yaml_fs' | 
 |  | 
 | if 'nodes_uri' not in options: | 
 |     nodes_uri = os.path.join(ansible_dir, 'nodes') | 
 |     if stat.S_ISDIR(os.stat(nodes_uri).st_mode): | 
 |         options['nodes_uri'] = nodes_uri | 
 |     else: | 
 |         usage_error('nodes_uri not specified') | 
 |  | 
 | if 'classes_uri' not in options: | 
 |     classes_uri = os.path.join(ansible_dir, 'classes') | 
 |     if not stat.S_ISDIR(os.stat(classes_uri).st_mode): | 
 |         classes_uri = options['nodes_uri'] | 
 |     options['classes_uri'] = classes_uri | 
 |  | 
 | # Invoke reclass according to what Ansible wants. | 
 | # If the 'node' option is set, we want node information. If the option is | 
 | # False instead, we print the inventory. Yeah for option abuse! | 
 | if sys.argv[1] == '--list': | 
 |     if len(sys.argv) > 2: | 
 |         usage_error('Unknown arguments: ' + ' '.join(sys.argv[2:])) | 
 |     options['node'] = False | 
 |  | 
 | elif sys.argv[1] == '--host': | 
 |     if len(sys.argv) < 3: | 
 |         usage_error('Missing hostname.') | 
 |     elif len(sys.argv) > 3: | 
 |         usage_error('Unknown arguments: ' + ' '.join(sys.argv[3:])) | 
 |     options['node'] = sys.argv[2] | 
 |  | 
 | else: | 
 |     usage_error('Unknown mode (--list or --host required).') | 
 |  | 
 | data = reclass.get_data(options['storage_type'], options['nodes_uri'], | 
 |                         options['classes_uri'], options['node']) | 
 |  | 
 | if options['node']: | 
 |     # Massage and shift the data like Ansible wants it | 
 |     data['parameters']['RECLASS'] = data['RECLASS'] | 
 |     for i in ('classes', 'applications'): | 
 |         data['parameters']['RECLASS'][i] = data[i] | 
 |     data = data['parameters'] | 
 |  | 
 | print reclass.output(data, options['output'], options['pretty_print']) | 
 |  | 
 | sys.exit(posix.EX_OK) |