abf-console-client-src/abf/api/jsn.py
Anton Kirilenko 0f7786cb39 Unification
2012-10-26 13:21:25 +04:00

192 lines
No EOL
7.2 KiB
Python

import urllib2, urllib
import re
import json
import os
import base64
import pdb
from abf.api.exceptions import *
from beaker.cache import Cache
from beaker.util import parse_cache_config_options
cache_data = Cache('abf_etag_data', expire = 86400, type='file', data_dir='/tmp/abf_cache/etag_data', lock_dir='/tmp/abf_cache/etag_data')
cache_etags = Cache('abf_etags', expire = 86400, type='file', data_dir='/tmp/abf_cache/etags', lock_dir='/tmp/abf_cache/etags')
class AbfJson(object):
def __init__(self,abf_url, login, password, log):
self.login = login
self.password = password
self.abf_url = re.compile('/+$').sub('',abf_url)
#does not work sometimes
'''self.password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
self.password_manager.add_password(None, abf_url, login, password)
self.auth = urllib2.HTTPBasicAuthHandler(self.password_manager)
self.opener = urllib2.build_opener(self.auth)
urllib2.install_opener(self.opener)
'''
# but it works!
self.base64_auth_string = base64.standard_b64encode('%s:%s' % (login, password)).replace('\n', '')
self.log = log
errors = {
"Invalid email or password.": AuthError,
"403 Forbidden | Rate Limit Exceeded": RateLimitError,
"Page not found": PageNotFoundError,
"Error 404. Resource not found!": PageNotFoundError,
"Something went wrong. We've been notified about this issue and we'll take a look at it shortly.": InternalServerError,
"We update the site, it will take some time. We are really trying to do it fast. We apologize for any inconvenience..": ServerWorksError,
"Requires authentication": AuthError,
"Forbidden. Sorry, you don't have enough rights for this action!": ForbiddenError,
"Access violation to this page!": ForbiddenError,
"Bad Request": BadRequestError,}
good_messages = ['Errors during build publishing!', 'Build is queued for publishing']
# in case of this error, get_url_contents will print the error message and exit
fatal_errors = [AuthError, RateLimitError, InternalServerError, ServerWorksError]
def get_url_contents(self, url, GET=None, POST=None):
url = self.abf_url + url
if GET:
get_string = urllib.urlencode(GET)
if '?' in url:
url = url + '&' + get_string
else:
url = url + '?' + get_string
self.log.debug('Fetching url %s' % url)
etag = None
if POST:
post_json = json.dumps(POST).encode('utf-8')
request = urllib2.Request(url, post_json, {'Content-Type': 'application/json'})
else:
request = urllib2.Request(url)
if cache_etags.has_key(url) :
etag = cache_etags.get(url)
self.log.debug("It was cached! ETag: " + etag)
request.add_header("If-None-Match", etag)
request.add_header("Authorization", "Basic %s" % self.base64_auth_string)
etag_new = None
try:
result = urllib2.urlopen(request)
res = result.read()
etag_new = result.headers.getheaders('ETag')[0]
except urllib2.HTTPError, ex:
if ex.code == 304: # data was not modified
res = cache_data.get(etag)
self.log.debug('Getting cached result (cache was validated)')
else:
self.log.debug('Return code: ' + str(ex.code))
if ex.code == 401: # auth failed
self.log.error("Authorization failed. Incorrect username or password")
exit()
#remove cached data if exists
if etag:
try:
cache_etags.remove(url)
cache_data.remove(etag)
except:
pass
res = ex.fp.read()
if etag_new:
self.log.debug("Caching the new value for %s. ETag is %s" % (url, etag_new))
cache_etags.put(url, etag_new)
cache_data.put(etag_new, res)
try:
res = json.loads(res)
except ValueError, ex:
self.log.error("Internal server error: it have returned non-json data. ")
exit(1)
if 'message' in res and res['message'] not in AbfJson.good_messages:
m = res['message']
if m in AbfJson.errors:
self.log.debug(m)
exception = AbfJson.errors[m]
else:
self.log.error("Unknown server error: " + m)
exception = AbfApiException
if exception == BadRequestError:
log.error('Sorry, but something went wrong and request I\'ve sent to ABF is bad. Please, '
'notify developers, send them a set of command-line arguments and the request data:\n%s\n%s' % (URL, post_json or "No POST DATA") )
exit(1)
if exception in AbfJson.fatal_errors:
exit(2)
raise exception(m)
#print 'RAW OUTPUT', res
return res
def get_architectures(self):
URL = "/api/v1/arches.json"
return self.get_url_contents(URL)
def get_platforms(self, typ=None):
URL = "/api/v1/platforms.json"
GET = {}
if typ:
GET['type'] = typ
return self.get_url_contents(URL, GET)
def get_platform_by_id(self, pl_id):
pl_id = int(pl_id)
URL = "/api/v1/platforms/%d.json" % pl_id
return self.get_url_contents(URL)
def get_build_platforms(self):
URL = "/api/v1/platforms/platforms_for_build.json"
return self.get_url_contents(URL)
def get_repository_by_id(self, rep_id):
rep_id = int(rep_id)
URL = "/api/v1/repositories/%d.json" % rep_id
return self.get_url_contents(URL)
def get_buildlist_by_id(self, bl_id):
bl_id = int(bl_id)
URL = "/api/v1/build_lists/%d.json" % bl_id
return self.get_url_contents(URL)
def get_project_by_id(self, p_id):
p_id = int(p_id)
URL = "/api/v1/projects/%d.json" % p_id
return self.get_url_contents(URL)
def get_project_id_by_name(self, key):
proj_owner, proj_name = key
URL = "/api/v1/projects/get_id.json"
GET = {'name': proj_name, 'owner':proj_owner}
return self.get_url_contents(URL, GET)
def new_build_task(self, data):
URL = "/api/v1/build_lists.json"
return self.get_url_contents(URL, GET=None, POST=data)
def publish(self, task_id):
task_id = int(task_id)
URL = "/api/v1/build_lists/%d/publish.json" % task_id
return self.get_url_contents(URL)
def get_git_refs_list(self, proj_id):
proj_id = int(proj_id)
URL = "/api/v1/projects/%d/refs_list.json" % proj_id
return self.get_url_contents(URL)
def get_user_by_id(self, user_id):
user_id = int(user_id)
URL = "/api/v1/users/%d.json" % user_id
return self.get_url_contents(URL)