debian-koji/devtools/fakehub
2023-05-09 09:24:34 +02:00

178 lines
4.9 KiB
Python
Executable file

#!/usr/bin/python3
from __future__ import absolute_import, print_function
import ast
import io
import optparse
import os
import os.path
import pprint
import sys
from urllib.parse import quote
sys.path.insert(0, os.getcwd())
import koji
from kojihub import auth, kojixmlrpc, kojihub
from koji.context import context
import koji.xmlrpcplus
# alternate handle_rpc, used when --pdb is given
original_handle_rpc = kojixmlrpc.ModXMLRPCRequestHandler.handle_rpc
def handle_rpc(self, environ):
try:
return original_handle_rpc(self, environ)
except Exception:
import pdb
import traceback
etype, e, tb = sys.exc_info()
traceback.print_exc()
pdb.post_mortem(tb)
# re-raise or the app handler will commit
raise
# Fake session for authenticated calls
class FakeSession(auth.Session):
def __init__(self, user, exclusive=False):
user = kojihub.get_user(user, strict=True)
self.logged_in = True
self.id = 1
self.user_id = user['id']
self.authtype = koji.AUTHTYPES['GSSAPI']
self.hostip = '127.0.0.1'
self.master = None
self.callnum = 1
self.message = 'THIS IS A FAKE SESSION'
self.exclusive = exclusive
self.user_data = user
self.session_data = {'msg': 'this is a fake session'}
self._perms = None
self._groups = None
self._host_id = ''
original_check_session = kojixmlrpc.ModXMLRPCRequestHandler.check_session
# alternate check_session, used to emulate auth
def check_session(self):
if 'KOJI_FAKEHUB_USER' in context.environ:
context.session = FakeSession(context.environ['KOJI_FAKEHUB_USER'],
context.environ.get('KOJI_FAKEHUB_EXCLUSIVE', False))
else:
original_check_session(self)
def get_url(environ):
url = environ['wsgi.url_scheme']+'://'
if environ.get('HTTP_HOST'):
url += environ['HTTP_HOST']
else:
url += environ['SERVER_NAME']
if environ['wsgi.url_scheme'] == 'https':
if environ['SERVER_PORT'] != '443':
url += ':' + environ['SERVER_PORT']
else:
if environ['SERVER_PORT'] != '80':
url += ':' + environ['SERVER_PORT']
url += quote(environ.get('SCRIPT_NAME', ''))
url += quote(environ.get('PATH_INFO', ''))
if environ.get('QUERY_STRING'):
url += '?' + environ['QUERY_STRING']
return url
def nice_literal(value):
try:
return ast.literal_eval(value)
except (ValueError, SyntaxError):
return value
def get_options():
parser = optparse.OptionParser(usage='%prog [options] <policy_file>')
parser.add_option('--pdb', action='store_true',
help='drop into pdb on error')
parser.add_option('--user', '-u', help='execute as user')
parser.add_option('--exclusive', '-x', action='store_true',
help='emulate an exclusive session')
opts, args = parser.parse_args()
# parse request from args
method = args[0]
callargs = []
kwargs = {}
for s in args[1:]:
if '=' in s:
k, v = s.split('=', 1)
v = nice_literal(v)
kwargs[k] = v
else:
callargs.append(nice_literal(s))
callargs = koji.encode_args(*callargs, **kwargs)
opts.request = koji.xmlrpcplus.dumps(callargs, method, allow_none=1)
return opts
def start_response(status, headers):
pprint.pprint("Status: %r" % status)
pprint.pprint("Headers: %r" % headers)
def parse_response(data):
p, u = koji.xmlrpcplus.getparser()
for chunk in data:
p.feed(chunk)
p.close()
result = u.close()
if len(result) == 1:
result = result[0]
return result
def set_config(environ):
lconfig = "%s/devtools/fakehub.conf" % os.getcwd()
lconfigd = "%s/devtools/fakehub.conf.d" % os.getcwd()
if os.path.exists(lconfig) or os.path.exists(lconfigd):
environ['koji.hub.ConfigFile'] = lconfig
environ['koji.hub.ConfigDir'] = lconfigd
def main():
options = get_options()
if options.pdb:
kojixmlrpc.ModXMLRPCRequestHandler.handle_rpc = handle_rpc
environ = {}
environ['SCRIPT_FILENAME'] = kojixmlrpc.__file__
environ['wsgi.url_scheme'] = 'https'
environ['SERVER_NAME'] = 'myserver'
environ['SERVER_PORT'] = '443'
environ['REQUEST_URI'] = get_url(environ)
environ['wsgi.input'] = io.StringIO(options.request)
environ['REQUEST_METHOD'] = 'POST'
environ['CONTENT_TYPE'] = 'text/xml'
if options.user:
environ['KOJI_FAKEHUB_USER'] = options.user
kojixmlrpc.ModXMLRPCRequestHandler.check_session = check_session
if options.exclusive:
environ['KOJI_FAKEHUB_EXCLUSIVE'] = True
set_config(environ)
print('RESULT:')
data = kojixmlrpc.application(environ, start_response)
result = parse_response(data)
pprint.pprint(result)
if __name__ == '__main__':
main()