diff --git a/openqa_review/browser.py b/openqa_review/browser.py index 571874e..a0a965c 100644 --- a/openqa_review/browser.py +++ b/openqa_review/browser.py @@ -74,7 +74,7 @@ class Browser(object): """download relative or absolute url and return soup.""" - def __init__(self, args, root_url, auth=None, headers={}): + def __init__(self, args, root_url, auth=None, headers={}, api_key=None): """Construct a browser object with options.""" self.save = args.save if hasattr(args, "save") else False self.load = args.load if hasattr(args, "load") else False @@ -83,6 +83,7 @@ def __init__(self, args, root_url, auth=None, headers={}): self.dry_run = args.dry_run if hasattr(args, "dry_run") else False self.root_url = root_url self.auth = auth + self.api_key = api_key headers["User-Agent"] = "openqa-review (https://os-autoinst.github.io/openqa_review)" self.headers = headers self.cache = {} @@ -185,9 +186,15 @@ def _decode_content(self, url, raw, as_json=False): raise DownloadError(msg) return content + def _params_with_login(self, params): + if self.api_key: + params["Bugzilla_api_key"] = self.api_key + return params + def json_rpc_get(self, url, method, params, cache=True): """Execute JSON RPC GET request.""" absolute_url = url if not url.startswith("/") else urljoin("http://dummy/", str(url)) + params = self._params_with_login(params) get_params = SortedDict({"method": method, "params": json.dumps([params])}) get_url = requests.Request("GET", absolute_url, params=get_params).prepare().url response = self.get_json(get_url.replace("http://dummy", ""), cache) @@ -204,6 +211,7 @@ def json_rpc_post(self, url, method, params): Supports a 'dry-run' which is only simulating the request with a log message. """ + params = self._params_with_login(params) if self.dry_run: log.warning("NOT sending '%s' request to '%s' with params %r" % (method, url, params)) return {} diff --git a/openqa_review/openqa_review.py b/openqa_review/openqa_review.py index ba0eb00..447aa55 100755 --- a/openqa_review/openqa_review.py +++ b/openqa_review/openqa_review.py @@ -149,6 +149,8 @@ def pluralize(_1, _2, plural): # local keyring if found #username = user #password = secret +# newer Bugzilla versions use an API key instead of username and password +#api_key = token base_url = https://apibugzilla.suse.com report_url = https://bugzilla.suse.com @@ -349,13 +351,18 @@ def progress_browser_factory(args): def bugzilla_browser_factory(args): + auth = () + # We need either an API key or login & password + if not config.has_option("product_issues", "api_key"): + auth = ( + config.get("product_issues", "username", fallback=None), + config.get("product_issues", "password", fallback=None), + ) return Browser( args, config.get("product_issues", "base_url"), - auth=( - config.get("product_issues", "username"), - config.get("product_issues", "password"), - ), + auth, + api_key=config.get("product_issues", "api_key", fallback=None), ) diff --git a/tests/test_openqa_review.py b/tests/test_openqa_review.py index cdfb503..9ad9057 100644 --- a/tests/test_openqa_review.py +++ b/tests/test_openqa_review.py @@ -699,6 +699,24 @@ def test_get_bugzilla_issue(): assert e.code == 300 +def test_bugzilla_with_api_key(): + openqa_review.config.remove_option("product_issues", "username") + openqa_review.config.remove_option("product_issues", "password") + openqa_review.config.set("product_issues", "api_key", "token") + args = cache_test_args_factory() + args.load_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "bugzilla") + browser = openqa_review.bugzilla_browser_factory(args) + assert browser.api_key, "API key used" + issue = openqa_review.Issue( + "boo#0815", + "https://bugzilla.opensuse.org/show_bug.cgi?id=0815", + query_issue_status=True, + bugzilla_browser=browser, + progress_browser=browser, + ) + assert issue.bugid == 815, "Bugzilla issue parsed" + + def test_querying_last_bugzilla_comment(): args = cache_test_args_factory() args.load_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "bugzilla")