1# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Encapsulates a simplistic interface to the buildbucket service."""
6
7import json
8
9from apiclient import discovery
10import httplib2
11
12from dashboard import utils
13
14_DISCOVERY_URL = (
15    'https://cr-buildbucket.appspot.com'
16    '/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest')
17
18# Default Buildbucket bucket name.
19_BUCKET_NAME = 'master.tryserver.chromium.perf'
20
21
22def _DiscoverService():
23  return discovery.build('buildbucket', 'v1',
24                         discoveryServiceUrl=_DISCOVERY_URL)
25
26
27class _AuthenticatedHttp(object):
28  """Provides access via its constructor to a singleton authenticated http."""
29
30  _singleton = None
31  _singleton_credentials = None
32
33  def __new__(cls, credentials):
34    if credentials and credentials != cls._singleton_credentials:
35      cls._singleton_credentials = credentials
36      cls._MakeSingleton(credentials)
37    if not cls._singleton:
38      cls._MakeSingleton()
39    assert cls._singleton
40    return cls._singleton
41
42  @classmethod
43  def _MakeSingleton(cls, override_credentials=None):
44    """Instantiates the singleton."""
45    # Uses rietveld credentials to authorize an http client. Note this same
46    # account is authorized for buildbucket.
47    cls._singleton = httplib2.Http()
48    if override_credentials:
49      credentials = override_credentials
50    else:
51      credentials = utils.ServiceAccountCredentials()
52
53    # If we cannot pull the credentials from ndb we simply use the unauthorized
54    # client. This useful when running a local dev server.
55    if credentials:
56      credentials.authorize(cls._singleton)
57
58
59def PutJob(job, bucket=_BUCKET_NAME, credentials=None):
60  """Creates a job via buildbucket's API."""
61  parameters = job.GetBuildParameters()
62  service = _DiscoverService()
63  request = service.put(
64      body={
65          'bucket': bucket,
66          'parameters_json': json.dumps(parameters),
67      })
68  response_content = request.execute(http=_AuthenticatedHttp(credentials))
69  job.response_fields = response_content.get('build')
70  return job.response_fields.get('id')
71
72
73def GetJobStatus(job_id, credentials=None):
74  """Gets the details of a job via buildbucket's API."""
75  service = _DiscoverService()
76  request = service.get(id=job_id)
77  response_content = request.execute(http=_AuthenticatedHttp(credentials))
78  return response_content
79
80# TODO(robertocn): Implement CancelJobByID
81