Skip to content

Commit 84a774e

Browse files
committed
Use wrapper shell script for systems without a "/usr/bin/env python"
Some systems (Ubuntu 17.04+) have nothing for "/usr/bin/env python". The have python3 instead. This commit introduces a wrapper script that finds out which python binary to use. Instead of linking bin/ansible-cmdb directly to lib/ansible-cmdb (the python script), we now link to the wrapper script.
1 parent 355b145 commit 84a774e

File tree

2 files changed

+236
-202
lines changed

2 files changed

+236
-202
lines changed

src/ansible-cmdb

Lines changed: 28 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -1,208 +1,34 @@
1-
#!/usr/bin/env python
1+
#!/bin/sh
22

3-
# ansible_cmd
43
#
5-
# Generate host overview (configuration management database) from ansible fact
6-
# gathering output.
7-
#
8-
# Usage:
9-
#
10-
# $ ansible -m setup --tree out all
11-
# $ ansible-cmdb out > cmdb.html
4+
# Wrapper script to find python version to use.
125
#
136

14-
import optparse
15-
import sys
16-
import os
17-
import logging
18-
from mako import exceptions
19-
import ansiblecmdb
20-
import ansiblecmdb.util as util
21-
import ansiblecmdb.render as render
22-
7+
# Find python binary
8+
PY_BIN=$(which python)
9+
if [ -z "$PY_BIN" ]; then
10+
PY_BIN=$(which python3)
11+
fi
2312

2413
# Verify Python version
25-
if sys.version_info < (2, 7):
26-
sys.stderr.write(
27-
"Ansible-cmdb requires Python v2.7+. You are running {}. Support for "
28-
"Python v2.6 supported ended October 2013. You should upgrade to a "
29-
"newer version.\n".format(sys.version))
30-
sys.exit(1)
31-
32-
33-
def get_logger():
34-
"""
35-
Instantiate a logger.
36-
"""
37-
root = logging.getLogger()
38-
root.setLevel(logging.WARNING)
39-
ch = logging.StreamHandler(sys.stderr)
40-
ch.setLevel(logging.DEBUG)
41-
formatter = logging.Formatter('%(message)s')
42-
ch.setFormatter(formatter)
43-
root.addHandler(ch)
44-
return root
45-
46-
47-
def get_data_dir():
48-
"""
49-
Find out our installation prefix and data directory. These can be in
50-
different places depending on how ansible-cmdb was installed.
51-
"""
52-
data_dir_paths = [
53-
os.path.join(os.path.dirname(ansiblecmdb.__file__), 'data'),
54-
os.path.join(os.path.dirname(sys.argv[0]), '..', 'lib', 'ansiblecmdb', 'data'),
55-
'/usr/local/lib/ansiblecmdb/data',
56-
'/usr/lib/ansiblecmdb/data',
57-
]
58-
59-
data_dir = util.find_path(data_dir_paths, 'tpl/html_fancy.tpl')
60-
if not data_dir:
61-
sys.stdout.write("Couldn't find the data dir for the templates. I tried: {0}\n".format(", ".join(data_dir_paths)))
62-
sys.exit(1)
63-
64-
return data_dir
65-
66-
67-
def get_hosts_files(option):
68-
"""
69-
Find out the location of the `hosts` file. This looks in multiple places
70-
such as the `-i` option, current dir and ansible configuration files. The
71-
first match is returned as a list.
72-
"""
73-
if option is not None:
74-
return option.split(',')
75-
76-
# Use hosts file from the current dir if it exists
77-
if os.path.isfile('hosts'):
78-
return ['hosts']
79-
80-
# Perhaps it's configured in a configuration file. Try to find a
81-
# configuration file and see if it contains a `hostsfile` entry.
82-
config_locations = [
83-
'.',
84-
'/etc/ansible/'
85-
]
86-
config_dir = util.find_path(config_locations, 'ansible.cfg')
87-
log.debug('config_dir = {0}'.format(config_dir))
88-
if config_dir:
89-
with open(os.path.join(config_dir, 'ansible.cfg'), 'r') as cf:
90-
for line in cf:
91-
if line.startswith('hostfile'):
92-
return [line.split('=', 1)[1].strip()]
93-
94-
95-
def parse_user_params(user_params):
96-
"""
97-
Parse the user params (-p/--params) and them as a dict.
98-
"""
99-
if user_params:
100-
params = {}
101-
try:
102-
for param in options.params.split(','):
103-
param_key, param_value = param.split('=', 1)
104-
params[param_key] = param_value
105-
except ValueError as e:
106-
sys.stdout.write("Invalid params specified. Should be in format: <key=value>[,<key=value>..]\n")
107-
sys.exit(1)
108-
return params
109-
else:
110-
return {}
111-
112-
113-
if __name__ == "__main__":
114-
log = get_logger()
115-
data_dir = get_data_dir()
116-
tpl_dir = os.path.join(data_dir, 'tpl')
117-
static_dir = os.path.join(data_dir, 'static')
118-
version = open(os.path.join(data_dir, 'VERSION')).read().strip()
119-
120-
parser = optparse.OptionParser(version="%prog v{0}".format(version))
121-
parser.set_usage(sys.argv[0] + " [option] <dir> > output.html")
122-
parser.add_option("-t", "--template", dest="template", action="store", default='html_fancy', help="Template to use. Default is 'html_fancy'")
123-
parser.add_option("-i", "--inventory", dest="inventory", action="store", default=None, help="Inventory to read extra info from")
124-
parser.add_option("-f", "--fact-cache", dest="fact_cache", action="store_true", default=False, help="<dir> contains fact-cache files")
125-
parser.add_option("-p", "--params", dest="params", action="store", default=None, help="Params to send to template")
126-
parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False, help="Show debug output")
127-
parser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=False, help="Don't report warnings")
128-
parser.add_option("-c", "--columns", dest="columns", action="store", default=None, help="Show only given columns")
129-
parser.add_option("--exclude-cols", dest="exclude_columns", action="store", default=None, help="Exclude cols from output")
130-
(options, args) = parser.parse_args()
131-
132-
if len(args) < 1:
133-
parser.print_usage()
134-
sys.stderr.write("The <dir> argument is mandatory\n")
135-
sys.exit(1)
136-
137-
if options.quiet:
138-
log.setLevel(logging.ERROR)
139-
elif options.debug:
140-
log.setLevel(logging.DEBUG)
141-
142-
hosts_files = get_hosts_files(options.inventory)
143-
144-
# Handle template params
145-
params = {
146-
'lib_dir': data_dir, # Backwards compatibility for custom templates < ansible-cmdb v1.7
147-
'data_dir': data_dir,
148-
'version': version,
149-
'log': log,
150-
'columns': None,
151-
'exclude_columns': None,
152-
}
153-
params.update(parse_user_params(options.params))
154-
if options.columns is not None:
155-
params['columns'] = options.columns.split(',')
156-
if options.exclude_columns is not None:
157-
params['exclude_columns'] = options.exclude_columns.split(',')
158-
159-
# Log some debug information
160-
log.debug('data_dir = {0}'.format(data_dir))
161-
log.debug('tpl_dir = {0}'.format(tpl_dir))
162-
log.debug('static_dir = {0}'.format(static_dir))
163-
log.debug('inventory files = {0}'.format(hosts_files))
164-
log.debug('template params = {0}'.format(params))
165-
166-
ansible = ansiblecmdb.Ansible(args, hosts_files, options.fact_cache, debug=options.debug)
167-
168-
# Render a template with the gathered host info
169-
renderer = render.Render(options.template, ['.', tpl_dir])
170-
if renderer.tpl_file is None:
171-
sys.stderr.write("Template '{0}' not found at any of \n {1}\n".format(options.template, "\n ".join(renderer.tpl_possibilities)))
172-
sys.exit(1)
173-
174-
# Make sure we always output in UTF-8, regardless of the user's locale /
175-
# terminal encoding. This is different in Python 2 and 3.
176-
try:
177-
output = renderer.render(ansible.hosts, params)
178-
if output:
179-
if sys.version_info[0] == 3:
180-
sys.stdout.buffer.write(output.lstrip())
181-
else:
182-
sys.stdout.write(output.lstrip())
183-
except Exception as err:
184-
full_err = exceptions.text_error_template().render().replace("\n", "\n ")
185-
debug_cmd = "{0} -d {1}".format(sys.argv[0], ' '.join(sys.argv[1:]))
186-
debug_txt = ("Whoops, it looks like something went wrong while rendering the template.\n\n"
187-
"The reported error was: {0}: {1}\n\nThe full error was:{2}\n"
188-
"The output is probably not correct.\n\n".format(err.__class__.__name__, err, full_err))
189-
if err.__class__.__name__ == "KeyError":
190-
debug_txt += "!!! This is probably a problem with missing information in your host facts\n\n"
191-
if not options.debug:
192-
debug_txt += ("You can re-run ansible-cmdb with the -d switch to turn on debugging\n"
193-
"to get an insight in what might be going wrong:\n\n"
194-
" {0}\n\n".format(debug_cmd))
195-
debug_txt += \
196-
"""\
197-
You can report a bug on the issue tracker:
198-
199-
https://github.com/fboender/ansible-cmdb/issues
200-
201-
Please include the debugging output (-d switch) in the report!
202-
203-
If you can, also include the hosts file and the facts file for the last host
204-
that rendered properly ('Rendering host...' in the output. If these files must
205-
remain confidential, you can send them to ferry.boender@gmail.com instead.
206-
"""
207-
sys.stderr.write(debug_txt)
208-
sys.exit(1)
14+
PY_VMAJOR=$($PY_BIN -c "import sys; print(sys.version_info.major)")
15+
PY_VMINOR=$($PY_BIN -c "import sys; print(sys.version_info.minor)")
16+
17+
if [ "$PY_VMAJOR" -eq 2 -a "$PY_VMINOR" -lt 7 ]; then
18+
echo "Python v2.7 or v3.0 or higher is required" >&2
19+
exit 1
20+
fi
21+
22+
# Find path to the real ansible-cmdb python script
23+
BIN_DIR=$(dirname $0)
24+
if [ -f "$BIN_DIR/ansible-cmdb.py" ]; then
25+
ANSIBLE_CMDB="$BIN_DIR/ansible-cmdb.py"
26+
elif [ -f "$BIN_DIR/../lib/ansible-cmdb/ansible-cmdb.py" ]; then
27+
ANSIBLE_CMDB="$BIN_DIR/../lib/ansible-cmdb/ansible-cmdb.py"
28+
else
29+
echo "Couldn't find $BIN_DIR/ansible-cmdb.py in . or $BIN_DIR/../lib/ansible-cmdb (cwd=$PWD)" >&2
30+
exit 2
31+
fi
32+
33+
# Run it
34+
$PY_BIN $ANSIBLE_CMDB "$@"

0 commit comments

Comments
 (0)