blob: 380ffe6d0bbb889f633e048c85de7f60734828b6 [file] [log] [blame]
martin f. krafft42c475d2013-06-26 18:39:06 +02001#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# salt-adapter — adapter between Salt and reclass
5#
6# Note that this file is not really necessary and exists mostly for debugging
7# purposes and admin joys. Have a look at README.Salt for proper integration
8# between Salt and reclass.
9#
10# Copyright © 2007–13 martin f. krafft <madduck@madduck.net>
11# Released under the terms of the Artistic Licence 2.0
12#
13__name__ = 'salt-reclass'
14__description__ = 'reclass adapter for Salt'
15__version__ = '1.0'
16__author__ = 'martin f. krafft <madduck@madduck.net>'
17__copyright__ = 'Copyright © 2007–13 ' + __author__
18__licence__ = 'Artistic Licence 2.0'
19
20import sys, os, posix
21
22# In order to be able to use reclass as modules, manipulate the search
23# path, starting from the location of the adapter. Realpath will make
24# sure that symlinks are resolved.
25realpath = os.path.realpath(sys.argv[0] + '/../../')
26sys.path.insert(0, realpath)
27
28import os, sys, posix
29import reclass.config
30from reclass.output import OutputLoader
31from reclass.storage import StorageBackendLoader
32from reclass.errors import ReclassException, InvocationError
33from reclass import output
34from reclass.adapters.salt import ext_pillar, top
35
36def _error(msg, rc):
37 print >>sys.stderr, msg
38 sys.exit(rc)
39
40try:
41 if len(sys.argv) == 1:
42 raise InvocationError('Need to specify --top or --pillar.',
43 posix.EX_USAGE)
44
45 # initialise options and try to read ./reclass-config.yml, which is
46 # expected to sit next to the salt-reclass CLI
47 options = {'storage_type': 'yaml_fs',
48 'pretty_print' : True,
49 'output' : 'yaml'
50 }
51 basedir = os.path.dirname(sys.argv[0])
52 config_path = os.path.join(basedir, 'reclass-config.yml')
53 if os.path.exists(config_path) and os.access(config_path, os.R_OK):
54 options.update(reclass.config.read_config_file(config_path))
55
56 nodes_uri, classes_uri = reclass.config.path_mangler(options.get('inventory_base_uri'),
57 options.get('nodes_uri'),
58 options.get('classes_uri'))
59 options['nodes_uri'] = nodes_uri
60 options['classes_uri'] = classes_uri
61
62 if sys.argv[1] in ('--top', '-t'):
63 if len(sys.argv) > 2:
64 raise InvocationError('Unknown arguments: ' + \
65 ' '.join(sys.argv[2:]), posix.EX_USAGE)
66 node = False
67
68 elif sys.argv[1] in ('--pillar', '-p'):
69 if len(sys.argv) < 3:
70 raise InvocationError('Missing hostname.', posix.EX_USAGE)
71 elif len(sys.argv) > 3:
72 raise InvocationError('Unknown arguments: ' + \
73 ' '.join(sys.argv[3:]), posix.EX_USAGE)
74 node = sys.argv[2]
75
76 else:
77 raise InvocationError('Unknown mode (--top or --pillar required).',
78 posix.EX_USAGE)
79
80 if not node:
martin f. kraffte38475f2013-07-01 15:08:47 +020081 reclass_opts = options.copy()
82 del reclass_opts['output']
83 del reclass_opts['pretty_print']
84 data = top(**reclass_opts)
martin f. krafft42c475d2013-06-26 18:39:06 +020085
86 else:
martin f. kraffte38475f2013-07-01 15:08:47 +020087 pillar={}
88 data = ext_pillar(node, pillar, options.get('storage_type'),
martin f. krafft42c475d2013-06-26 18:39:06 +020089 options.get('inventory_base_uri'),
90 options.get('nodes_uri'),
91 options.get('classes_uri'))
92
93 print output(data, options.get('output'), options.get('pretty_print'))
94 sys.exit(posix.EX_OK)
95
96except ReclassException, e:
97 _error(e.message, e.rc)