blob: 1310c215931237ad4f9b46153ff3f44ef2431f8f [file] [log] [blame]
#! /usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
``ctx`` proxy client implementation.
"""
import argparse
import json
import os
import sys
import urllib2
# Environment variable for the socket url (used by clients to locate the socket)
CTX_SOCKET_URL = 'CTX_SOCKET_URL'
class _RequestError(RuntimeError):
def __init__(self, ex_message, ex_type, ex_traceback):
super(_RequestError, self).__init__(self, '{0}: {1}'.format(ex_type, ex_message))
self.ex_type = ex_type
self.ex_message = ex_message
self.ex_traceback = ex_traceback
def _http_request(socket_url, request, method, timeout):
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request(socket_url, data=json.dumps(request))
request.get_method = lambda: method
response = opener.open(request, timeout=timeout)
if response.code != 200:
raise RuntimeError('Request failed: {0}'.format(response))
return json.loads(response.read())
def _client_request(socket_url, args, timeout, method='POST'):
response = _http_request(
socket_url=socket_url,
request={'args': args},
method=method,
timeout=timeout
)
payload = response.get('payload')
response_type = response.get('type')
if response_type == 'error':
ex_type = payload['type']
ex_message = payload['message']
ex_traceback = payload['traceback']
raise _RequestError(ex_message, ex_type, ex_traceback)
elif response_type == 'stop_operation':
raise SystemExit(payload['message'])
else:
return payload
def _parse_args(args):
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--timeout', type=int, default=30)
parser.add_argument('--socket-url', default=os.environ.get(CTX_SOCKET_URL))
parser.add_argument('--json-arg-prefix', default='@')
parser.add_argument('-j', '--json-output', action='store_true')
parser.add_argument('args', nargs='*')
args = parser.parse_args(args=args)
if not args.socket_url:
raise RuntimeError('Missing CTX_SOCKET_URL environment variable '
'or socket_url command line argument. (ctx is supposed to be executed '
'within an operation context)')
return args
def _process_args(json_prefix, args):
processed_args = []
for arg in args:
if arg.startswith(json_prefix):
arg = json.loads(arg[1:])
processed_args.append(arg)
return processed_args
def main(args=None):
args = _parse_args(args)
response = _client_request(
args.socket_url,
args=_process_args(args.json_arg_prefix, args.args),
timeout=args.timeout)
if args.json_output:
response = json.dumps(response)
else:
if not response:
response = ''
response = str(response)
sys.stdout.write(response)
if __name__ == '__main__':
main()