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

Side by Side Diff: appengine/cr-buildbucket/api.py

Issue 1082303002: buildbucket: put_batch endpoint (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 8 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 | appengine/cr-buildbucket/errors.py » ('j') | appengine/cr-buildbucket/service.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import datetime 5 import datetime
6 import functools 6 import functools
7 import json 7 import json
8 import logging 8 import logging
9 9
10 from components import auth 10 from components import auth
(...skipping 25 matching lines...) Expand all
36 errors.InvalidBuildStateError: ErrorReason.INVALID_BUILD_STATE, 36 errors.InvalidBuildStateError: ErrorReason.INVALID_BUILD_STATE,
37 errors.BuildIsCompletedError: ErrorReason.BUILD_IS_COMPLETED, 37 errors.BuildIsCompletedError: ErrorReason.BUILD_IS_COMPLETED,
38 } 38 }
39 39
40 40
41 class ErrorMessage(messages.Message): 41 class ErrorMessage(messages.Message):
42 reason = messages.EnumField(ErrorReason, 1, required=True) 42 reason = messages.EnumField(ErrorReason, 1, required=True)
43 message = messages.StringField(2, required=True) 43 message = messages.StringField(2, required=True)
44 44
45 45
46 def exception_to_error_message(ex):
47 assert isinstance(ex, errors.Error)
48 return ErrorMessage(
49 reason=ERROR_REASON_MAP[type(ex)],
50 message=ex.message,
51 )
52
53
54 class PutRequestMessage(messages.Message):
55 bucket = messages.StringField(1, required=True)
56 tags = messages.StringField(2, repeated=True)
57 parameters_json = messages.StringField(3)
58 lease_expiration_ts = messages.IntegerField(4)
59
60
46 class BuildMessage(messages.Message): 61 class BuildMessage(messages.Message):
47 """Describes model.Build, see its docstring.""" 62 """Describes model.Build, see its docstring."""
48 id = messages.IntegerField(1, required=True) 63 id = messages.IntegerField(1, required=True)
49 bucket = messages.StringField(2, required=True) 64 bucket = messages.StringField(2, required=True)
50 tags = messages.StringField(3, repeated=True) 65 tags = messages.StringField(3, repeated=True)
51 parameters_json = messages.StringField(4) 66 parameters_json = messages.StringField(4)
52 status = messages.EnumField(model.BuildStatus, 5) 67 status = messages.EnumField(model.BuildStatus, 5)
53 result = messages.EnumField(model.BuildResult, 6) 68 result = messages.EnumField(model.BuildResult, 6)
54 result_details_json = messages.StringField(7) 69 result_details_json = messages.StringField(7)
55 failure_reason = messages.EnumField(model.FailureReason, 8) 70 failure_reason = messages.EnumField(model.FailureReason, 8)
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 endpoints_decorator = auth.endpoints_method( 164 endpoints_decorator = auth.endpoints_method(
150 request_message_class, response_message_class, **kwargs) 165 request_message_class, response_message_class, **kwargs)
151 166
152 def decorator(fn): 167 def decorator(fn):
153 @functools.wraps(fn) 168 @functools.wraps(fn)
154 def decorated(*args, **kwargs): 169 def decorated(*args, **kwargs):
155 try: 170 try:
156 return fn(*args, **kwargs) 171 return fn(*args, **kwargs)
157 except errors.Error as ex: 172 except errors.Error as ex:
158 assert hasattr(response_message_class, 'error') 173 assert hasattr(response_message_class, 'error')
159 return response_message_class(error=ErrorMessage( 174 return response_message_class(error=exception_to_error_message(ex))
160 reason=ERROR_REASON_MAP[type(ex)],
161 message=ex.message,
162 ))
163 return endpoints_decorator(decorated) 175 return endpoints_decorator(decorated)
164 return decorator 176 return decorator
165 177
166 178
167 def parse_json(json_data, param_name): 179 def parse_json(json_data, param_name):
168 if not json_data: 180 if not json_data:
169 return None 181 return None
170 try: 182 try:
171 return json.loads(json_data) 183 return json.loads(json_data)
172 except ValueError as ex: 184 except ValueError as ex:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 path='builds/{id}', http_method='GET') 223 path='builds/{id}', http_method='GET')
212 def get(self, request): 224 def get(self, request):
213 """Returns a build by id.""" 225 """Returns a build by id."""
214 build = self.service.get(request.id) 226 build = self.service.get(request.id)
215 if build is None: 227 if build is None:
216 raise errors.BuildNotFoundError() 228 raise errors.BuildNotFoundError()
217 return build_to_response_message(build) 229 return build_to_response_message(build)
218 230
219 ################################### PUT #################################### 231 ################################### PUT ####################################
220 232
221 class PutRequestMessage(messages.Message):
222 bucket = messages.StringField(1, required=True)
223 tags = messages.StringField(2, repeated=True)
224 parameters_json = messages.StringField(3)
225 lease_expiration_ts = messages.IntegerField(4)
226
227 @buildbucket_api_method( 233 @buildbucket_api_method(
228 PutRequestMessage, BuildResponseMessage, 234 PutRequestMessage, BuildResponseMessage,
229 path='builds', http_method='PUT') 235 path='builds', http_method='PUT')
230 def put(self, request): 236 def put(self, request):
231 """Creates a new build.""" 237 """Creates a new build."""
232 if not request.bucket:
233 raise errors.InvalidInputError('Bucket not specified')
234
235 build = self.service.add( 238 build = self.service.add(
236 bucket=request.bucket, 239 bucket=request.bucket,
237 tags=request.tags, 240 tags=request.tags,
238 parameters=parse_json(request.parameters_json, 'parameters_json'), 241 parameters=parse_json(request.parameters_json, 'parameters_json'),
239 lease_expiration_date=parse_datetime(request.lease_expiration_ts), 242 lease_expiration_date=parse_datetime(request.lease_expiration_ts),
240 ) 243 )
241 return build_to_response_message(build, include_lease_key=True) 244 return build_to_response_message(build, include_lease_key=True)
242 245
246 ################################ PUT_BATCH #################################
247
248 class PutBatchRequestMessage(messages.Message):
249 builds = messages.MessageField(PutRequestMessage, 1, repeated=True)
250
251 class PutBatchResponseMessage(messages.Message):
252 builds = messages.MessageField(BuildMessage, 1, repeated=True)
253 error = messages.MessageField(ErrorMessage, 2)
254
255 @buildbucket_api_method(
256 PutBatchRequestMessage, PutBatchResponseMessage,
257 path='builds/batch', http_method='PUT')
258 def put_batch(self, request):
Vadim Sh. 2015/04/14 18:56:40 btw, apiary APIs exposed by Google support batchin
nodir 2015/04/14 22:13:05 It cannot
259 """Creates up to 25 new builds transactionally."""
260 builds = self.service.add_batch([
261 {
262 'bucket': build_req.bucket,
263 'tags': build_req.tags,
264 'parameters': parse_json(
265 build_req.parameters_json, 'parameters_json'),
266 'lease_expiration_date': parse_datetime(
267 build_req.lease_expiration_ts),
268 }
269 for build_req in request.builds
270 ])
271 return self.PutBatchResponseMessage(
272 builds=[build_to_message(b, include_lease_key=True) for b in builds],
273 )
274
275
243 ################################## SEARCH ################################# 276 ################################## SEARCH #################################
244 277
245 SEARCH_REQUEST_RESOURCE_CONTAINER = endpoints.ResourceContainer( 278 SEARCH_REQUEST_RESOURCE_CONTAINER = endpoints.ResourceContainer(
246 message_types.VoidMessage, 279 message_types.VoidMessage,
247 start_cursor=messages.StringField(1), 280 start_cursor=messages.StringField(1),
248 # All specified tags must be present in a build. 281 # All specified tags must be present in a build.
249 bucket=messages.StringField(2, repeated=True), 282 bucket=messages.StringField(2, repeated=True),
250 tag=messages.StringField(3, repeated=True), 283 tag=messages.StringField(3, repeated=True),
251 status=messages.EnumField(model.BuildStatus, 4), 284 status=messages.EnumField(model.BuildStatus, 4),
252 result=messages.EnumField(model.BuildResult, 5), 285 result=messages.EnumField(model.BuildResult, 5),
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 rules=[ 545 rules=[
513 acl.Rule( 546 acl.Rule(
514 role=rule.role, 547 role=rule.role,
515 group=rule.group, 548 group=rule.group,
516 ) 549 )
517 for rule in request.rules 550 for rule in request.rules
518 ], 551 ],
519 ) 552 )
520 bucket_acl = acl.set_acl(request.bucket, bucket_acl) 553 bucket_acl = acl.set_acl(request.bucket, bucket_acl)
521 return bucket_acl_to_response_message(bucket_acl) 554 return bucket_acl_to_response_message(bucket_acl)
OLDNEW
« no previous file with comments | « no previous file | appengine/cr-buildbucket/errors.py » ('j') | appengine/cr-buildbucket/service.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698