You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
britney2-ubuntu/britney2/policies/rest.py

65 lines
2.0 KiB

import json
import socket
import urllib.request
import urllib.parse
from collections import defaultdict
from urllib.error import HTTPError
LAUNCHPAD_URL = "https://api.launchpad.net/1.0/"
class Rest:
"""Wrap common REST APIs with some retry logic."""
def query_rest_api(self, obj, query):
"""Do a REST request
Request <obj>?<query>.
Returns string received from web service.
Raises HTTPError, ValueError, or ConnectionError based on different
transient failures connecting.
"""
for retry in range(5):
url = "%s?%s" % (obj, urllib.parse.urlencode(query))
try:
with urllib.request.urlopen(url, timeout=30) as req:
code = req.getcode()
if 200 <= code < 300:
return req.read().decode("UTF-8")
raise ConnectionError(
"Failed to reach launchpad, HTTP %s" % code
)
except socket.timeout as e:
self.logger.info(
"Timeout downloading '%s', will retry %d more times."
% (url, 5 - retry - 1)
)
exc = e
except HTTPError as e:
if e.code not in (503, 502):
raise
self.logger.info(
"Caught error %d downloading '%s', will retry %d more times."
% (e.code, url, 5 - retry - 1)
)
exc = e
else:
raise exc
def query_lp_rest_api(self, obj, query):
"""Do a Launchpad REST request
Request <LAUNCHPAD_URL><obj>?<query>.
Returns dict of parsed json result from launchpad.
Raises HTTPError, ValueError, or ConnectionError based on different
transient failures connecting to launchpad.
"""
if not obj.startswith(LAUNCHPAD_URL):
obj = LAUNCHPAD_URL + obj
return json.loads(self.query_rest_api(obj, query))