Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: rietveld.py

Issue 932333003: Make maxtries for Rietveld configurable (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # coding: utf-8 1 # coding: utf-8
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 """Defines class Rietveld to easily access a rietveld instance. 5 """Defines class Rietveld to easily access a rietveld instance.
6 6
7 Security implications: 7 Security implications:
8 8
9 The following hypothesis are made: 9 The following hypothesis are made:
10 - Rietveld enforces: 10 - Rietveld enforces:
(...skipping 19 matching lines...) Expand all
30 import third_party.oauth2client.client as oa2client 30 import third_party.oauth2client.client as oa2client
31 from third_party import httplib2 31 from third_party import httplib2
32 32
33 # Appengine replies with 302 when authentication fails (sigh.) 33 # Appengine replies with 302 when authentication fails (sigh.)
34 oa2client.REFRESH_STATUS_CODES.append(302) 34 oa2client.REFRESH_STATUS_CODES.append(302)
35 upload.LOGGER.setLevel(logging.WARNING) # pylint: disable=E1103 35 upload.LOGGER.setLevel(logging.WARNING) # pylint: disable=E1103
36 36
37 37
38 class Rietveld(object): 38 class Rietveld(object):
39 """Accesses rietveld.""" 39 """Accesses rietveld."""
40 def __init__(self, url, email, password, extra_headers=None): 40 def __init__(self, url, email, password, extra_headers=None, maxtries=None):
41 self.url = url.rstrip('/') 41 self.url = url.rstrip('/')
42 # Email and password are accessed by commit queue, keep them. 42 # Email and password are accessed by commit queue, keep them.
43 self.email = email 43 self.email = email
44 self.password = password 44 self.password = password
45 # TODO(maruel): It's not awesome but maybe necessary to retrieve the value. 45 # TODO(maruel): It's not awesome but maybe necessary to retrieve the value.
46 # It happens when the presubmit check is ran out of process, the cookie 46 # It happens when the presubmit check is ran out of process, the cookie
47 # needed to be recreated from the credentials. Instead, it should pass the 47 # needed to be recreated from the credentials. Instead, it should pass the
48 # email and the cookie. 48 # email and the cookie.
49 if email and password: 49 if email and password:
50 get_creds = lambda: (email, password) 50 get_creds = lambda: (email, password)
51 self.rpc_server = upload.HttpRpcServer( 51 self.rpc_server = upload.HttpRpcServer(
52 self.url, 52 self.url,
53 get_creds, 53 get_creds,
54 extra_headers=extra_headers or {}) 54 extra_headers=extra_headers or {})
55 else: 55 else:
56 if email == '': 56 if email == '':
57 # If email is given as an empty string, then assume we want to make 57 # If email is given as an empty string, then assume we want to make
58 # requests that do not need authentication. Bypass authentication by 58 # requests that do not need authentication. Bypass authentication by
59 # setting the auth_function to None. 59 # setting the auth_function to None.
60 self.rpc_server = upload.HttpRpcServer(url, None) 60 self.rpc_server = upload.HttpRpcServer(url, None)
61 else: 61 else:
62 self.rpc_server = upload.GetRpcServer(url, email) 62 self.rpc_server = upload.GetRpcServer(url, email)
63 63
64 self._xsrf_token = None 64 self._xsrf_token = None
65 self._xsrf_token_time = None 65 self._xsrf_token_time = None
66 66
67 self._maxtries = maxtries or 40
68
67 def xsrf_token(self): 69 def xsrf_token(self):
68 if (not self._xsrf_token_time or 70 if (not self._xsrf_token_time or
69 (time.time() - self._xsrf_token_time) > 30*60): 71 (time.time() - self._xsrf_token_time) > 30*60):
70 self._xsrf_token_time = time.time() 72 self._xsrf_token_time = time.time()
71 self._xsrf_token = self.get( 73 self._xsrf_token = self.get(
72 '/xsrf_token', 74 '/xsrf_token',
73 extra_headers={'X-Requesting-XSRF-Token': '1'}) 75 extra_headers={'X-Requesting-XSRF-Token': '1'})
74 return self._xsrf_token 76 return self._xsrf_token
75 77
76 def get_pending_issues(self): 78 def get_pending_issues(self):
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 def trap_http_500(msg): 408 def trap_http_500(msg):
407 """Converts an incorrect ErrorExit() call into a HTTPError exception.""" 409 """Converts an incorrect ErrorExit() call into a HTTPError exception."""
408 m = re.search(r'(50\d) Server Error', msg) 410 m = re.search(r'(50\d) Server Error', msg)
409 if m: 411 if m:
410 # Fake an HTTPError exception. Cheezy. :( 412 # Fake an HTTPError exception. Cheezy. :(
411 raise urllib2.HTTPError( 413 raise urllib2.HTTPError(
412 request_path, int(m.group(1)), msg, None, None) 414 request_path, int(m.group(1)), msg, None, None)
413 old_error_exit(msg) 415 old_error_exit(msg)
414 upload.ErrorExit = trap_http_500 416 upload.ErrorExit = trap_http_500
415 417
416 maxtries = 40 418 for retry in xrange(self._maxtries):
417 for retry in xrange(maxtries):
418 try: 419 try:
419 logging.debug('%s' % request_path) 420 logging.debug('%s' % request_path)
420 result = self.rpc_server.Send(request_path, **kwargs) 421 result = self.rpc_server.Send(request_path, **kwargs)
421 # Sometimes GAE returns a HTTP 200 but with HTTP 500 as the content. 422 # Sometimes GAE returns a HTTP 200 but with HTTP 500 as the content.
422 # How nice. 423 # How nice.
423 return result 424 return result
424 except urllib2.HTTPError, e: 425 except urllib2.HTTPError, e:
425 if retry >= (maxtries - 1): 426 if retry >= (self._maxtries - 1):
426 raise 427 raise
427 flake_codes = [500, 502, 503] 428 flake_codes = [500, 502, 503]
428 if retry_on_404: 429 if retry_on_404:
429 flake_codes.append(404) 430 flake_codes.append(404)
430 if e.code not in flake_codes: 431 if e.code not in flake_codes:
431 raise 432 raise
432 except urllib2.URLError, e: 433 except urllib2.URLError, e:
433 if retry >= (maxtries - 1): 434 if retry >= (self._maxtries - 1):
434 raise 435 raise
435 if (not 'Name or service not known' in e.reason and 436 if (not 'Name or service not known' in e.reason and
436 not 'EOF occurred in violation of protocol' in e.reason): 437 not 'EOF occurred in violation of protocol' in e.reason):
437 # Usually internal GAE flakiness. 438 # Usually internal GAE flakiness.
438 raise 439 raise
439 except ssl.SSLError, e: 440 except ssl.SSLError, e:
440 if retry >= (maxtries - 1): 441 if retry >= (self._maxtries - 1):
441 raise 442 raise
442 if not 'timed out' in str(e): 443 if not 'timed out' in str(e):
443 raise 444 raise
444 # If reaching this line, loop again. Uses a small backoff. 445 # If reaching this line, loop again. Uses a small backoff.
445 time.sleep(min(10, 1+retry*2)) 446 time.sleep(min(10, 1+retry*2))
446 finally: 447 finally:
447 upload.ErrorExit = old_error_exit 448 upload.ErrorExit = old_error_exit
448 449
449 # DEPRECATED. 450 # DEPRECATED.
450 Send = get 451 Send = get
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 This class is supposed to be used only by bots, since this kind of 569 This class is supposed to be used only by bots, since this kind of
569 access is restricted to service accounts. 570 access is restricted to service accounts.
570 """ 571 """
571 # The parent__init__ is not called on purpose. 572 # The parent__init__ is not called on purpose.
572 # pylint: disable=W0231 573 # pylint: disable=W0231
573 def __init__(self, 574 def __init__(self,
574 url, 575 url,
575 client_email, 576 client_email,
576 client_private_key_file, 577 client_private_key_file,
577 private_key_password=None, 578 private_key_password=None,
578 extra_headers=None): 579 extra_headers=None,
580 maxtries=None):
579 581
580 # These attributes are accessed by commit queue. Keep them. 582 # These attributes are accessed by commit queue. Keep them.
581 self.email = client_email 583 self.email = client_email
582 self.private_key_file = client_private_key_file 584 self.private_key_file = client_private_key_file
583 585
584 if private_key_password is None: # '' means 'empty password' 586 if private_key_password is None: # '' means 'empty password'
585 private_key_password = 'notasecret' 587 private_key_password = 'notasecret'
586 588
587 self.url = url.rstrip('/') 589 self.url = url.rstrip('/')
588 bot_url = self.url + '/bots' 590 bot_url = self.url + '/bots'
589 591
590 with open(client_private_key_file, 'rb') as f: 592 with open(client_private_key_file, 'rb') as f:
591 client_private_key = f.read() 593 client_private_key = f.read()
592 logging.info('Using OAuth login: %s' % client_email) 594 logging.info('Using OAuth login: %s' % client_email)
593 self.rpc_server = OAuthRpcServer(bot_url, 595 self.rpc_server = OAuthRpcServer(bot_url,
594 client_email, 596 client_email,
595 client_private_key, 597 client_private_key,
596 private_key_password=private_key_password, 598 private_key_password=private_key_password,
597 extra_headers=extra_headers or {}) 599 extra_headers=extra_headers or {})
598 self._xsrf_token = None 600 self._xsrf_token = None
599 self._xsrf_token_time = None 601 self._xsrf_token_time = None
600 602
603 self._maxtries = 40 or maxtries
Michael Achenbach 2015/02/19 11:20:33 Hmm, sad that there's no super call.
Jens Widell 2015/02/19 11:32:39 This is the same as "self._maxtries = 40". Did you
Michael Achenbach 2015/02/19 11:33:56 Ups, totally missed that. Good catch!
Paweł Hajdan Jr. 2015/02/19 11:49:04 Good catch, fixed in https://codereview.chromium.o
604
601 605
602 class CachingRietveld(Rietveld): 606 class CachingRietveld(Rietveld):
603 """Caches the common queries. 607 """Caches the common queries.
604 608
605 Not to be used in long-standing processes, like the commit queue. 609 Not to be used in long-standing processes, like the commit queue.
606 """ 610 """
607 def __init__(self, *args, **kwargs): 611 def __init__(self, *args, **kwargs):
608 super(CachingRietveld, self).__init__(*args, **kwargs) 612 super(CachingRietveld, self).__init__(*args, **kwargs)
609 self._cache = {} 613 self._cache = {}
610 614
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 self, issue, patchset, reason, clobber, revision, builders_and_tests, 729 self, issue, patchset, reason, clobber, revision, builders_and_tests,
726 master=None, category='cq'): 730 master=None, category='cq'):
727 logging.info('ReadOnlyRietveld: triggering try jobs %r for issue %d' % 731 logging.info('ReadOnlyRietveld: triggering try jobs %r for issue %d' %
728 (builders_and_tests, issue)) 732 (builders_and_tests, issue))
729 733
730 def trigger_distributed_try_jobs( # pylint:disable=R0201 734 def trigger_distributed_try_jobs( # pylint:disable=R0201
731 self, issue, patchset, reason, clobber, revision, masters, 735 self, issue, patchset, reason, clobber, revision, masters,
732 category='cq'): 736 category='cq'):
733 logging.info('ReadOnlyRietveld: triggering try jobs %r for issue %d' % 737 logging.info('ReadOnlyRietveld: triggering try jobs %r for issue %d' %
734 (masters, issue)) 738 (masters, issue))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698