xref: /illumos-gate/usr/src/tools/onbld/Checks/DbLookups.py (revision 4b9db4f6425b1a08fca4390f446072c4a6aae8d5)
1#! /usr/bin/python
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
24# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25#
26
27# Copyright 2010, Richard Lowe
28# Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
29# Copyright 2024 Oxide Computer Company
30
31#
32# Various database lookup classes/methods, i.e.:
33#     * monaco
34#     * bugs.opensolaris.org (b.o.o.)
35#     * redmine (illumos.org)
36#
37
38import re
39try:
40	from urllib.request import urlopen, Request
41	from urllib.error import HTTPError
42except ImportError:
43	# Python 2
44	from urllib2 import Request, urlopen, HTTPError
45
46try:				# Python >= 2.5
47	from xml.etree import ElementTree
48except ImportError:
49	from elementtree import ElementTree
50
51class NonExistentBug(Exception):
52	def __str__(self):
53		return "Bug %s does not exist" % (Exception.__str__(self))
54
55class BugDBException(Exception):
56	def __str__(self):
57		return "Unknown bug database: %s" % (Exception.__str__(self))
58
59class BugDB(object):
60	"""Lookup change requests.
61
62	Usage:
63	bdb = BugDB()
64	r = bdb.lookup("6455550")
65	print r["6455550"]["synopsis"]
66	r = bdb.lookup(["6455550", "6505625"])
67	print r["6505625"]["synopsis"]
68	"""
69
70	VALID_DBS = ["illumos"]
71
72	def __init__(self, priority = ["illumos"]):
73		"""Create a BugDB object.
74
75		Keyword argument:
76		priority: use bug databases in this order
77		"""
78		for database in priority:
79			if database not in self.VALID_DBS:
80				raise BugDBException(database)
81		self.__priority = priority
82
83
84	def __illbug(self, cr):
85		url = "http://illumos.org/issues/%s.xml" % cr
86		req = Request(
87			url,
88			headers = {
89				"User-Agent": "git-pbchk"
90			}
91		)
92
93		try:
94			data = urlopen(req)
95		except HTTPError as e:
96			if e.code == 401 or e.code == 404:
97				raise NonExistentBug(cr)
98			else:
99				raise
100
101		bug = ElementTree.parse(data)
102
103		return {'cr_number': bug.find('id').text,
104			'synopsis': bug.find('subject').text,
105			'status': bug.find('status').attrib['name']
106		}
107
108
109	def lookup(self, crs):
110		"""Return all info for requested change reports.
111
112		Argument:
113		crs: one change request id (may be integer, string, or list),
114		     or multiple change request ids (must be a list)
115
116		Returns:
117		Dictionary, mapping CR=>dictionary, where the nested dictionary
118		is a mapping of field=>value
119		"""
120		results = {}
121		if not isinstance(crs, list):
122			crs = [str(crs)]
123		for database in self.__priority:
124			if database == "illumos":
125				for cr in crs:
126					try:
127						results[str(cr)] = self.__illbug(cr)
128					except NonExistentBug:
129						continue
130
131			# the CR has already been found by one bug database
132			# so don't bother looking it up in the others
133			for cr in crs:
134				if cr in results:
135					crs.remove(cr)
136
137		return results
138