awx/ansibleworks/scripts/inventory.py
2013-06-20 04:20:59 -04:00

121 lines
5.2 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright (c) 2013 AnsibleWorks, Inc.
# All Rights Reserved.
# Python
import json
import optparse
import os
import sys
import urllib
import urlparse
# Requests
import requests
class TokenAuth(requests.auth.AuthBase):
def __init__(self, token):
self.token = token
def __call__(self, request):
request.headers['Authorization'] = 'Token %s' % self.token
return request
class InventoryScript(object):
def __init__(self, **options):
self.options = options
def get_data(self):
parts = urlparse.urlsplit(self.base_url)
if parts.username and parts.password:
auth = (parts.username, parts.password)
elif self.auth_token:
auth = TokenAuth(self.auth_token)
else:
auth = None
url = urlparse.urlunsplit([parts.scheme,
'%s:%d' % (parts.hostname, parts.port),
parts.path, parts.query, parts.fragment])
url_path = '/api/v1/inventories/%d/script/' % self.inventory_id
if self.hostname:
url_path += '?%s' % urllib.urlencode({'host': self.hostname})
url = urlparse.urljoin(url, url_path)
response = requests.get(url, auth=auth)
response.raise_for_status()
sys.stdout.write(json.dumps(response.json(), indent=self.indent) + '\n')
def run(self):
try:
self.base_url = self.options.get('base_url', '') or \
os.getenv('REST_API_URL', '')
if not self.base_url:
raise ValueError('No REST API URL specified')
self.auth_token = self.options.get('authtoken', '') or \
os.getenv('REST_API_TOKEN', '')
parts = urlparse.urlsplit(self.base_url)
if not (parts.username and parts.password) and not self.auth_token:
raise ValueError('No REST API token or username/password '
'specified')
try:
# Command line argument takes precedence over environment
# variable.
self.inventory_id = int(self.options.get('inventory_id', 0) or \
os.getenv('INVENTORY_ID', 0))
except ValueError:
raise ValueError('Inventory ID must be an integer')
if not self.inventory_id:
raise ValueError('No inventory ID specified')
self.hostname = self.options.get('hostname', '')
self.list_ = self.options.get('list', False)
self.indent = self.options.get('indent', None)
if self.list_ and self.hostname:
raise RuntimeError('Only --list or --host may be specified')
elif self.list_ or self.hostname:
self.get_data()
else:
raise RuntimeError('Either --list or --host must be specified')
except Exception, e:
# Always return an empty hash on stdout, even when an error occurs.
sys.stdout.write(json.dumps({}))
#print >> file(os.path.join(os.path.dirname(__file__), 'foo.log'), 'a'), repr(e)
#if hasattr(e, 'response'):
# print >> file(os.path.join(os.path.dirname(__file__), 'foo.log'), 'a'), e.response.content
if self.options.get('traceback', False):
raise
sys.stderr.write(str(e) + '\n')
if hasattr(e, 'response'):
sys.stderr.write(e.response.content + '\n')
sys.exit(1)
def main():
parser = optparse.OptionParser()
parser.add_option('-v', '--verbosity', action='store', dest='verbosity',
default='1', type='choice', choices=['0', '1', '2', '3'],
help='Verbosity level; 0=minimal output, 1=normal output'
', 2=verbose output, 3=very verbose output')
parser.add_option('--traceback', action='store_true',
help='Raise on exception on error')
parser.add_option('-u', '--url', dest='base_url', default='',
help='Base URL to access REST API (can also be specified'
' using REST_API_URL environment variable)')
parser.add_option('--authtoken', dest='authtoken', default='',
help='Authentication token used to access REST API (can '
'also be specified using REST_API_TOKEN environment '
'variable)')
parser.add_option('-i', '--inventory', dest='inventory_id', type='int',
default=0, help='Inventory ID (can also be specified '
'using INVENTORY_ID environment variable)')
parser.add_option('--list', action='store_true', dest='list',
default=False, help='Return JSON hash of host groups.')
parser.add_option('--host', dest='hostname', default='',
help='Return JSON hash of host vars.')
parser.add_option('--indent', dest='indent', type='int', default=None,
help='Indentation level for pretty printing output')
options, args = parser.parse_args()
InventoryScript(**vars(options)).run()
if __name__ == '__main__':
main()