def search(self, query): """ Perform GitHub query """ result = [] url = self.url + "/" + query + f"&per_page={PER_PAGE}" while True: # Fetch the query log.debug(f"GitHub query: {url}") try: response = requests.get(url, headers=self.headers) log.debug(f"Response headers:\n{response.headers}") except requests.exceptions.RequestException as error: log.debug(error) raise ReportError(f"GitHub search on {self.url} failed.") # Parse fetched json data try: data = json.loads(response.text)["items"] result.extend(data) except requests.exceptions.JSONDecodeError as error: log.debug(error) raise ReportError(f"GitHub JSON failed: {response.text}.") # Update url to the next page, break if no next page provided if 'next' in response.links: url = response.links['next']['url'] else: break log.debug("Result: {0} fetched".format(listed(len(result), "item"))) log.data(pretty(result)) return result
def __init__(self, option, name=None, parent=None, user=None): """ Process config, prepare investigator, construct stats """ # Check Request Tracker instance url and custom prefix StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) try: self.url = config["url"] except KeyError: raise ReportError( "No url in the [{0}] section".format(option)) try: self.prefix = config["prefix"] except KeyError: raise ReportError( "No prefix set in the [{0}] section".format(option)) # Save Ticket class as attribute to allow customizations by # descendant class and set up the RequestTracker investigator self.ticket = Ticket self.request_tracker = RequestTracker(parent=self) # Construct the list of stats self.stats = [ ReportedTickets(option=option + "-reported", parent=self), ResolvedTickets(option=option + "-resolved", parent=self), ]
def __init__(self, option, name=None, parent=None, user=None): name = "Tickets in {0}".format(option) StatsGroup.__init__(self, option, name, parent, user) # Initialize the server proxy config = dict(Config().section(option)) if "url" not in config: raise ReportError( "No trac url set in the [{0}] section".format(option)) self.url = re.sub("/rpc$", "", config["url"]) self.proxy = xmlrpc.client.ServerProxy(self.url + "/rpc") # Make sure we have prefix set if "prefix" not in config: raise ReportError( "No prefix set in the [{0}] section".format(option)) self.prefix = config["prefix"] # Create the list of stats self.stats = [ TracCreated(option=option + "-created", parent=self, name="Tickets created in {0}".format(option)), TracAccepted(option=option + "-accepted", parent=self, name="Tickets accepted in {0}".format(option)), TracUpdated(option=option + "-updated", parent=self, name="Tickets updated in {0}".format(option)), TracClosed(option=option + "-closed", parent=self, name="Tickets closed in {0}".format(option)), ]
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check server url try: self.url = config["url"] except KeyError: raise ReportError( "No GitLab url set in the [{0}] section".format(option)) # Check authorization token try: self.token = config["token"] except KeyError: raise ReportError( "No GitLab token set in the [{0}] section".format(option)) # Check SSL verification try: self.ssl_verify = bool( distutils.util.strtobool(config["ssl_verify"])) except KeyError: self.ssl_verify = GITLAB_SSL_VERIFY if not self.ssl_verify: requests.packages.urllib3.disable_warnings(InsecureRequestWarning) self.gitlab = GitLab(self.url, self.token, self.ssl_verify) # Create the list of stats self.stats = [ IssuesCreated(option=option + "-issues-created", parent=self, name="Issues created on {0}".format(option)), IssuesCommented(option=option + "-issues-commented", parent=self, name="Issues commented on {0}".format(option)), IssuesClosed(option=option + "-issues-closed", parent=self, name="Issues closed on {0}".format(option)), MergeRequestsCreated( option=option + "-merge-requests-created", parent=self, name="Merge requests created on {0}".format(option)), MergeRequestsCommented( option=option + "-merge-requests-commented", parent=self, name="Issues commented on {0}".format(option)), MergeRequestsApproved( option=option + "-merge-requests-approved", parent=self, name="Merge requests approved on {0}".format(option)), MergeRequestsClosed( option=option + "-merge-requests-closed", parent=self, name="Merge requests closed on {0}".format(option)), ]
def get(self, path): """ Perform a GET request with GSSAPI authentication """ # Generate token service_name = gssapi.Name('HTTP@{0}'.format(self.url.netloc), gssapi.NameType.hostbased_service) ctx = gssapi.SecurityContext(usage="initiate", name=service_name) data = b64encode(ctx.step()).decode() # Make the connection connection = httplib.HTTPSConnection(self.url.netloc, 443) log.debug("GET {0}".format(path)) connection.putrequest("GET", path) connection.putheader("Authorization", "Negotiate {0}".format(data)) connection.putheader("Referer", self.url_string) connection.endheaders() # Perform the request, convert response into lines response = connection.getresponse() if response.status != 200: raise ReportError( "Failed to fetch tickets: {0}".format(response.status)) lines = response.read().decode("utf8").strip().split("\n")[1:] log.debug("Tickets fetched:") log.debug(pretty(lines)) return lines
def session(self): """ Initialize the session """ if self._session is None: self._session = requests.Session() log.debug("Connecting to {0}".format(self.auth_url)) # Disable SSL warning when ssl_verify is False if not self.ssl_verify: requests.packages.urllib3.disable_warnings( InsecureRequestWarning) if self.auth_type == "basic": basic_auth = (self.auth_username, self.auth_password) response = self._session.get(self.auth_url, auth=basic_auth, verify=self.ssl_verify) else: gssapi_auth = HTTPSPNEGOAuth(mutual_authentication=DISABLED) response = self._session.get(self.auth_url, auth=gssapi_auth, verify=self.ssl_verify) try: response.raise_for_status() except requests.exceptions.HTTPError as error: log.error(error) raise ReportError( "Confluence authentication failed. Try kinit.") return self._session
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) self.config = dict(Config().section(option)) if 'url' not in self.config: raise IOError( 'No gerrit URL set in the [{0}] section'.format(option)) self.repo_url = self.config['url'] log.debug('repo_url = {0}'.format(self.repo_url)) if "prefix" not in self.config: raise ReportError( "No prefix set in the [{0}] section".format(option)) self.server_features = [] if self.config.get('wip', True) == True: self.server_features.append('wip') self.stats = [ AbandonedChanges(option=option + '-abandoned', parent=self), MergedChanges(option=option + '-merged', parent=self), SubmitedChanges(option=option + '-submitted', parent=self), WIPChanges(option=option + '-wip', parent=self), #AddedPatches(option=option + '-added-patches', parent=self), ReviewedChanges(option=option + '-reviewed', parent=self), ]
def search(query, stats): """ Perform issue search for given stats instance """ log.debug("Search query: {0}".format(query)) issues = [] # Fetch data from the server in batches of MAX_RESULTS issues for batch in range(MAX_BATCHES): response = stats.parent.session.get( "{0}/rest/api/latest/search?{1}".format( stats.parent.url, urllib.parse.urlencode({ "jql": query, "fields": "summary,comment", "maxResults": MAX_RESULTS, "startAt": batch * MAX_RESULTS}))) data = response.json() if not response.ok: try: error = " ".join(data["errorMessages"]) except KeyError: error = "unknown" raise ReportError( f"Failed to fetch jira issues for query '{query}'. " f"The reason was '{response.reason}' " f"and the error was '{error}'.") log.debug("Batch {0} result: {1} fetched".format( batch, listed(data["issues"], "issue"))) log.data(pretty(data)) issues.extend(data["issues"]) # If all issues fetched, we're done if len(issues) >= data["total"]: break # Return the list of issue objects return [Issue(issue, prefix=stats.parent.prefix) for issue in issues]
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check server url try: self.url = config["url"] except KeyError: raise ReportError( "No github url set in the [{0}] section".format(option)) # Check authorization token try: self.token = config["token"] except KeyError: self.token = None self.github = GitHub(self.url, self.token) # Create the list of stats self.stats = [ IssuesCreated( option=option + "-issues-created", parent=self, name="Issues created on {0}".format(option)), IssuesClosed( option=option + "-issues-closed", parent=self, name="Issues closed on {0}".format(option)), PullRequestsCreated( option=option + "-pull-requests-created", parent=self, name="Pull requests created on {0}".format(option)), PullRequestsClosed( option=option + "-pull-requests-closed", parent=self, name="Pull requests closed on {0}".format(option)), PullRequestsReviewed( option=option + "-pull-requests-reviewed", parent=self, name="Pull requests reviewed on {0}".format(option)), ]
def __init__(self, option, name=None, parent=None, user=None): name = "Redmine activity on {0}".format(option) super(RedmineStats, self).__init__(option=option, name=name, parent=parent, user=user) StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check server url try: self.url = config["url"] except KeyError: raise ReportError( "No Redmine url set in the [{0}] section".format(option)) try: self.activity_days = datetime.timedelta(config["activity_days"]) except KeyError: # 30 is value of activity_days_default self.activity_days = datetime.timedelta(30) # Create the list of stats self.stats = [ RedmineActivity(option="{0}-activity".format(option), parent=self, name="Redmine activity on {0}".format(option)), ]
def get(self, path): """ Perform a GET request with Kerberos authentication """ # Prepare Kerberos ticket granting ticket """ _, ctx = kerberos.authGSSClientInit( 'HTTP@{0}'.format(self.url.netloc)) kerberos.authGSSClientStep(ctx, "") tgt = kerberos.authGSSClientResponse(ctx) # Make the connection connection = httplib.HTTPSConnection(self.url.netloc, 443) log.debug("GET {0}".format(path)) connection.putrequest("GET", path) connection.putheader("Authorization", "Negotiate {0}".format(tgt)) connection.putheader("Referer", self.url_string) connection.endheaders() # Perform the request, convert response into lines response = connection.getresponse() if response.status != 200: raise ReportError( "Failed to fetch tickets: {0}".format(response.status)) lines = response.read().decode("utf8").strip().split("\n")[1:] log.debug("Tickets fetched:") log.debug(pretty(lines)) return lines
def session(self): """ Initialize the session """ if self._session is None: self._session = requests.Session() log.debug("Connecting to {0}".format(self.auth_url)) if self.auth_type == 'basic': data = { "username": self.auth_username, "password": self.auth_password } headers = { "Content-type": "application/json", "Accept": "application/json" } response = self._session.get(self.auth_url, headers=headers, data=data) else: gssapi_auth = HTTPSPNEGOAuth(mutual_authentication=DISABLED) response = self._session.get(self.auth_url, auth=gssapi_auth) try: response.raise_for_status() except requests.exceptions.HTTPError as error: log.error(error) raise ReportError('Jira authentication failed. Try kinit.') return self._session
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check server url try: self.url = config['url'] except KeyError: raise ReportError( 'No Pagure url set in the [{0}] section'.format(option)) # Check authorization token try: self.token = config['token'] except KeyError: self.token = None self.pagure = Pagure(self.url, self.token) # Create the list of stats self.stats = [ IssuesCreated(option=option + '-issues-created', parent=self, name='Issues created on {0}'.format(option)), IssuesClosed(option=option + '-issues-closed', parent=self, name='Issues closed on {0}'.format(option)), PullRequestsCreated( option=option + '-pull-requests-created', parent=self, name='Pull requests created on {0}'.format(option)), # FIXME: Blocked by https://pagure.io/pagure/issue/4329 # PullRequestsClosed( # option=option + '-pull-requests-closed', parent=self, # name='Pull requests closed on {0}'.format(option)), ]
def get_user(self, username): query = 'users?username={0}'.format(username) result = self._get_gitlab_api_json(query) try: return result[0] except IndexError: raise ReportError( "Unable to find user '{0}' on GitLab.".format(username))
def __init__(self, option, name=None, parent=None, user=None): name = "Trello updates for {0}".format(option) super(TrelloStatsGroup, self).__init__(option=option, name=name, parent=parent, user=user) # map appropriate API methods to Classes filter_map = { 'Boards': {}, 'Lists': {}, 'Cards': { 'commentCard': TrelloCardsCommented, 'updateCard': TrelloCardsUpdated, 'updateCard:closed': TrelloCardsClosed, 'updateCard:idList': TrelloCardsMoved, 'createCard': TrelloCardsCreated }, 'Checklists': { 'updateCheckItemStateOnCard': TrelloCheckItem } } self._session = None self.url = "https://trello.com/1" config = dict(Config().section(option)) positional_args = ['apikey', 'token'] if (not set(positional_args).issubset(set(config.keys())) and "user" not in config): raise ReportError( "No ({0}) or 'user' set in the [{1}] section".format( listed(positional_args, quote="'"), option)) optional_args = ["board_links", "apikey", "token"] for arg in optional_args: if arg not in config: config[arg] = "" # Skip API instance initialization when building options if self.options is None: trello = None else: trello = TrelloAPI(stats=self, config=config) try: filters = split(config["filters"]) except KeyError: filters = DEFAULT_FILTERS for filt_group in sorted(filter_map): for filt in sorted(filter_map[filt_group]): if filters != [""] and filt not in filters: continue self.stats.append(filter_map[filt_group][filt](trello=trello, filt=filt, option=option + "-" + filt, parent=self))
def session(self): """ Initialize the session """ if self._session is None: self._session = requests.Session() log.debug("Connecting to {0}".format(self.auth_url)) # Disable SSL warning when ssl_verify is False if not self.ssl_verify: requests.packages.urllib3.disable_warnings( InsecureRequestWarning) if self.auth_type == 'basic': basic_auth = (self.auth_username, self.auth_password) response = self._session.get( self.auth_url, auth=basic_auth, verify=self.ssl_verify) elif self.auth_type == "token": self.session.headers["Authorization"] = f"Bearer {self.token}" response = self._session.get( "{0}/rest/api/2/myself".format(self.url), verify=self.ssl_verify) else: gssapi_auth = HTTPSPNEGOAuth(mutual_authentication=DISABLED) response = self._session.get( self.auth_url, auth=gssapi_auth, verify=self.ssl_verify) try: response.raise_for_status() except requests.exceptions.HTTPError as error: log.error(error) raise ReportError( "Jira authentication failed. Check credentials or kinit.") if self.token_expiration: response = self._session.get( "{0}/rest/pat/latest/tokens".format(self.url), verify=self.ssl_verify) try: response.raise_for_status() token_found = None for token in response.json(): if token["name"] == self.token_name: token_found = token break if token_found is None: raise ValueError( f"Can't check validity for the '{self.token_name}' " f"token as it doesn't exist.") from datetime import datetime expiring_at = datetime.strptime( token_found["expiringAt"], r"%Y-%m-%dT%H:%M:%S.%f%z") delta = ( expiring_at.astimezone() - datetime.now().astimezone()) if delta.days < self.token_expiration: log.warn( f"Jira token '{self.token_name}' " f"expires in {delta.days} days.") except (requests.exceptions.HTTPError, KeyError, ValueError) as error: log.warn(error) return self._session
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check server url try: self.url = config["url"] except KeyError: raise ReportError( "No GitLab url set in the [{0}] section".format(option)) # Check authorization token try: self.token = config["token"] except KeyError: raise ReportError( "No GitLab token set in the [{0}] section".format(option)) self.gitlab = GitLab(self.url, self.token) # Create the list of stats self.stats = [ IssuesCreated(option=option + "-issues-created", parent=self, name="Issues created on {0}".format(option)), IssuesCommented(option=option + "-issues-commented", parent=self, name="Issues commented on {0}".format(option)), IssuesClosed(option=option + "-issues-closed", parent=self, name="Issues closed on {0}".format(option)), MergeRequestsCreated( option=option + "-merge-requests-created", parent=self, name="Merge requests created on {0}".format(option)), MergeRequestsCommented( option=option + "-merge-requests-commented", parent=self, name="Issues commented on {0}".format(option)), MergeRequestsClosed( option=option + "-merge-requests-closed", parent=self, name="Merge requests closed on {0}".format(option)), ]
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check Bugzilla instance url try: self.url = config["url"] except KeyError: raise ReportError( "No bugzilla url set in the [{0}] section".format(option)) # Make sure we have prefix set try: self.prefix = config["prefix"] except KeyError: raise ReportError( "No prefix set in the [{0}] section".format(option)) # Check for customized list of resolutions try: self.resolutions = [ resolution.lower() for resolution in split(config["resolutions"]) ] except KeyError: self.resolutions = DEFAULT_RESOLUTIONS # Save Bug class as attribute to allow customizations by # descendant class and set up the Bugzilla investigator self.bug = Bug self.bugzilla = Bugzilla(parent=self) # Construct the list of stats self.stats = [ FiledBugs(option=option + "-filed", parent=self), PatchedBugs(option=option + "-patched", parent=self), PostedBugs(option=option + "-posted", parent=self), FixedBugs(option=option + "-fixed", parent=self), ReturnedBugs(option=option + "-returned", parent=self), VerifiedBugs(option=option + "-verified", parent=self), CommentedBugs(option=option + "-commented", parent=self), SubscribedBugs(option=option + "-subscribed", parent=self), ClosedBugs(option=option + "-closed", parent=self), ]
def get_data(self): """ Get organization activity in JSON representation """ url = self.url + "organizations/" + self.organization + "/activity/" headers = {'Authorization': 'Bearer {0}'.format(self.token)} request = urllib2.Request(url, None, headers) log.debug("Getting activity data from server.") try: response = urllib2.urlopen(request) except urllib2.URLError as e: log.error("An error encountered while getting data from server.") log.debug(e) raise ReportError("Could not get data. {0}.".format(str(e))) return json.load(response)
def _fetch_activities(self): """ Get organization activity, handle pagination """ activities = [] # Prepare url of the first page url = '{0}/organizations/{1}/activity/'.format( self.url, self.organization) while url: # Fetch one page of activities try: log.debug('Fetching activity data: {0}'.format(url)) response = requests.get(url, headers=self.headers) if not response.ok: log.error(response.text) raise ReportError('Failed to fetch Sentry activities.') data = response.json() log.data("Response headers:\n{0}".format( pretty(response.headers))) log.debug("Fetched {0}.".format(listed(len(data), 'activity'))) log.data(pretty(data)) for activity in [Activity(item) for item in data]: # We've reached the last page, older records not relevant if activity.created < self.stats.options.since.date: return activities # Store only relevant activites (before until date) if activity.created < self.stats.options.until.date: log.details("Activity: {0}".format(activity)) activities.append(activity) except requests.RequestException as error: log.debug(error) raise ReportError( 'Failed to fetch Sentry activities from {0}'.format(url)) # Check for possible next page try: url = NEXT_PAGE.search(response.headers['Link']).groups()[0] except AttributeError: url = None return activities
def search(query, parent, options): """ Perform Trac search """ # Extend the default max number of tickets to be fetched query = "{0}&max={1}".format(query, MAX_TICKETS) log.debug("Search query: {0}".format(query)) try: result = parent.proxy.ticket.query(query) except xmlrpc.client.Fault as error: log.error("An error encountered, while searching for tickets.") raise ReportError(error) except xmlrpc.client.ProtocolError as error: log.debug(error) log.error("Trac url: {0}".format(parent.url)) raise ReportError( "Unable to contact Trac server. Is the url above correct?") log.debug("Search result: {0}".format(result)) # Fetch tickets and their history using multicall multicall = xmlrpc.client.MultiCall(parent.proxy) for ticket_id in sorted(result): multicall.ticket.get(ticket_id) multicall.ticket.changeLog(ticket_id) log.debug("Fetching trac tickets and their history") result = list(multicall()) tickets = result[::2] changelogs = result[1::2] # Print debugging info for ticket, changelog in zip(tickets, changelogs): log.debug("Fetched ticket #{0}".format(ticket[0])) log.debug(pretty(ticket)) log.debug("Changelog:") log.debug(pretty(changelog)) # Return the list of ticket objects return [ Trac(ticket, changelg, parent=parent, options=options) for ticket, changelg in zip(tickets, changelogs) ]
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check server url try: self.url = config['url'] except KeyError: raise ReportError( 'No Bodhi url set in the [{0}] section'.format(option)) self.bodhi = Bodhi(self.url) # Create the list of stats self.stats = [ UpdatesCreated(option=option + '-updates-created', parent=self, name='Updates created on {0}'.format(option)), ]
def search(self, query): """ Perform GitHub query """ url = self.url + "/" + query log.debug("GitHub query: {0}".format(url)) try: request = urllib.request.Request(url, headers=self.headers) response = urllib.request.urlopen(request) log.debug("Response headers:\n{0}".format( str(response.info()).strip())) except urllib.error.URLError as error: log.debug(error) raise ReportError("GitHub search on {0} failed.".format(self.url)) result = json.loads(response.read())["items"] log.debug("Result: {0} fetched".format(listed(len(result), "item"))) log.data(pretty(result)) return result
def session(self): """ Initialize the session """ if self._session is None: self._session = requests.Session() log.debug("Connecting to {0}".format(self.auth_url)) if self.auth_type == 'basic': basic_auth = (self.auth_username, self.auth_password) response = self._session.get(self.auth_url, auth=basic_auth) else: gssapi_auth = HTTPSPNEGOAuth(mutual_authentication=DISABLED) response = self._session.get(self.auth_url, auth=gssapi_auth) try: response.raise_for_status() except requests.exceptions.HTTPError as error: log.error(error) raise ReportError('Jira authentication failed. Try kinit.') return self._session
def search(self, query, options): """ Perform Bugzilla search """ query["query_format"] = "advanced" query["limit"] = "0" log.debug("Search query:") log.debug(pretty(query)) # Fetch bug info try: result = self.server.query(query) except xmlrpc.client.Fault as error: # Ignore non-existent users (this is necessary for users with # several email aliases to allow them using --merge/--total) if "not a valid username" in str(error): log.debug(error) return [] # Otherwise suggest to bake bugzilla cookies log.error("An error encountered, while searching for bugs.") log.debug(error) raise ReportError( "Have you baked cookies using the 'bugzilla login' command?") log.debug("Search result:") log.debug(pretty(result)) bugs = dict((bug.id, bug) for bug in result) # Fetch bug history log.debug("Fetching bug history") result = self.server._proxy.Bug.history({'ids': list(bugs.keys())}) log.debug(pretty(result)) history = dict((bug["id"], bug["history"]) for bug in result["bugs"]) # Fetch bug comments log.debug("Fetching bug comments") result = self.server._proxy.Bug.comments({'ids': list(bugs.keys())}) log.debug(pretty(result)) comments = dict((int(bug), data["comments"]) for bug, data in list(result["bugs"].items())) # Create bug objects return [ self.parent.bug(bugs[id], history[id], comments[id], parent=self.parent) for id in bugs ]
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) config = dict(Config().section(option)) # Check server url try: self.url = config["url"] except KeyError: raise ReportError( "No zammad url set in the [{0}] section".format(option)) # Check authorization token try: self.token = config["token"] except KeyError: self.token = None self.zammad = Zammad(self.url, self.token) # Create the list of stats self.stats = [ TicketsUpdated(option=option + "-tickets-updated", parent=self, name="Tickets updated on {0}".format(option)), ]
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) self.config = dict(Config().section(option)) if 'url' not in self.config: raise IOError( 'No gerrit URL set in the [{0}] section'.format(option)) self.repo_url = self.config['url'] log.debug('repo_url = {0}'.format(self.repo_url)) if "prefix" not in self.config: raise ReportError( "No prefix set in the [{0}] section".format(option)) self.stats = [ AbandonedChanges(option=option + '-abandoned', parent=self), MergedChanges(option=option + '-merged', parent=self), SubmitedChanges(option=option + '-submitted', parent=self), PublishedDrafts(option=option + '-drafts', parent=self), #AddedPatches(option=option + '-added-patches', parent=self), ReviewedChanges(option=option + '-reviewed', parent=self), ]
def search(self, query, pagination, result_field): """ Perform Pagure query """ result = [] url = "/".join((self.url, query)) while url: log.debug("Pagure query: {0}".format(url)) try: response = requests.get(url, headers=self.headers) log.data("Response headers:\n{0}".format(response.headers)) except requests.RequestException as error: log.error(error) raise ReportError("Pagure search {0} failed.".format(self.url)) data = response.json() objects = data[result_field] log.debug("Result: {0} fetched".format(listed( len(objects), "item"))) log.data(pretty(data)) # FIXME later: Work around https://pagure.io/pagure/issue/4057 if not objects: break result.extend(objects) url = data[pagination]['next'] return result
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) self._session = None # Make sure there is an url provided config = dict(Config().section(option)) if "url" not in config: raise ReportError( "No Jira url set in the [{0}] section".format(option)) self.url = config["url"].rstrip("/") # Optional authentication url if "auth_url" in config: self.auth_url = config["auth_url"] else: self.auth_url = self.url + "/step-auth-gss" # Authentication type if "auth_type" in config: if config["auth_type"] not in AUTH_TYPES: raise ReportError( "Unsupported authentication type: {0}" .format(config["auth_type"])) self.auth_type = config["auth_type"] else: self.auth_type = "gss" # Authentication credentials if self.auth_type == "basic": if "auth_username" not in config: raise ReportError( "`auth_username` not set in the [{0}] section" .format(option)) self.auth_username = config["auth_username"] if "auth_password" not in config: raise ReportError( "`auth_password` not set in the [{0}] section" .format(option)) self.auth_password = config["auth_password"] else: if "auth_username" in config: raise ReportError( "`auth_username` is only valid for basic authentication" + " (section [{0}])".format(option)) if "auth_password" in config: raise ReportError( "`auth_password` is only valid for basic authentication" + " (section [{0}])".format(option)) # Make sure we have project set if "project" not in config: raise ReportError( "No project set in the [{0}] section".format(option)) self.project = config["project"] # Check for custom prefix self.prefix = config["prefix"] if "prefix" in config else None # Create the list of stats self.stats = [ JiraCreated( option=option + "-created", parent=self, name="Issues created in {0}".format(option)), JiraUpdated( option=option + "-updated", parent=self, name="Issues updated in {0}".format(option)), JiraResolved( option=option + "-resolved", parent=self, name="Issues resolved in {0}".format(option)), ]
def __init__(self, option, name=None, parent=None, user=None): StatsGroup.__init__(self, option, name, parent, user) self._session = None # Make sure there is an url provided config = dict(Config().section(option)) if "url" not in config: raise ReportError( "No Confluence url set in the [{0}] section".format(option)) self.url = config["url"].rstrip("/") # Optional authentication url if "auth_url" in config: self.auth_url = config["auth_url"] else: self.auth_url = self.url + "/step-auth-gss" # Authentication type if "auth_type" in config: if config["auth_type"] not in AUTH_TYPES: raise ReportError( "Unsupported authentication type: {0}".format( config["auth_type"])) self.auth_type = config["auth_type"] else: self.auth_type = "gss" # Authentication credentials if self.auth_type == "basic": if "auth_username" not in config: raise ReportError( "`auth_username` not set in the [{0}] section".format( option)) self.auth_username = config["auth_username"] if "auth_password" in config: self.auth_password = config["auth_password"] elif "auth_password_file" in config: file_path = os.path.expanduser(config["auth_password_file"]) with open(file_path) as password_file: self.auth_password = password_file.read().strip() else: raise ReportError( "`auth_password` or `auth_password_file` must be set " "in the [{0}] section".format(option)) else: if "auth_username" in config: raise ReportError( "`auth_username` is only valid for basic authentication" + " (section [{0}])".format(option)) if "auth_password" in config or "auth_password_file" in config: raise ReportError( "`auth_password` and `auth_password_file` are only valid " "for basic authentication (section [{0}])".format(option)) # SSL verification if "ssl_verify" in config: try: self.ssl_verify = distutils.util.strtobool( config["ssl_verify"]) except Exception as error: raise ReportError( "Error when parsing 'ssl_verify': {0}".format(error)) else: self.ssl_verify = SSL_VERIFY self.login = config.get("login", None) # Check for custom prefix self.prefix = config["prefix"] if "prefix" in config else None # Create the list of stats self.stats = [ PageCreated(option=option + "-pages", parent=self, name="Pages created in {}".format(option)), CommentAdded(option=option + "-comments", parent=self, name="Comments added in {}".format(option)), ]