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

Side by Side Diff: appengine/swarming/message_conversion.py

Issue 2926713004: Add support for repeated keys in TaskRequest. (Closed)
Patch Set: rebase Created 3 years, 6 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 | « appengine/swarming/local_smoke_test.py ('k') | appengine/swarming/server/task_queues.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2015 The LUCI Authors. All rights reserved. 1 # Copyright 2015 The LUCI Authors. All rights reserved.
2 # Use of this source code is governed under the Apache License, Version 2.0 2 # Use of this source code is governed under the Apache License, Version 2.0
3 # that can be found in the LICENSE file. 3 # that can be found in the LICENSE file.
4 4
5 """This module facilitates conversion from dictionaries to ProtoRPC messages. 5 """This module facilitates conversion from dictionaries to ProtoRPC messages.
6 6
7 Given a dictionary whose keys' names and values' types comport with the 7 Given a dictionary whose keys' names and values' types comport with the
8 fields defined for a protorpc.messages.Message subclass, this module tries to 8 fields defined for a protorpc.messages.Message subclass, this module tries to
9 generate a Message instance that corresponds to the provided dictionary. The 9 generate a Message instance that corresponds to the provided dictionary. The
10 "normal" use case is for ndb.Models which need to be represented as a 10 "normal" use case is for ndb.Models which need to be represented as a
11 ProtoRPC. 11 ProtoRPC.
12 """ 12 """
13 13
14 import datetime 14 import datetime
15 import json 15 import json
16 16
17 import swarming_rpcs 17 import swarming_rpcs
18 18
19 from components import utils 19 from components import utils
20 from server import task_pack 20 from server import task_pack
21 from server import task_request 21 from server import task_request
22 from server import task_result 22 from server import task_result
23 23
24 24
25 ### Private API. 25 ### Private API.
26 26
27 27
28 def _string_pairs_from_dict(dictionary): 28 def _string_pairs_from_list_of_tuples(dictionary):
29 return [ 29 return [
30 swarming_rpcs.StringPair(key=k, value=v) 30 swarming_rpcs.StringPair(key=k, value=v)
31 for k, v in sorted((dictionary or {}).iteritems()) 31 for k, v in sorted((dictionary or []))
32 ] 32 ]
33 33
34 34
35 def _string_pairs_from_dict(dictionary):
36 return _string_pairs_from_list_of_tuples((dictionary or {}).iteritems())
37
38
35 def _string_list_pairs_from_dict(dictionary): 39 def _string_list_pairs_from_dict(dictionary):
36 return [ 40 return [
37 swarming_rpcs.StringListPair(key=k, value=v) 41 swarming_rpcs.StringListPair(key=k, value=v)
38 for k, v in sorted((dictionary or {}).iteritems()) 42 for k, v in sorted((dictionary or {}).iteritems())
39 ] 43 ]
40 44
41 45
42 def _ndb_to_rpc(cls, entity, **overrides): 46 def _ndb_to_rpc(cls, entity, **overrides):
43 members = (f.name for f in cls.all_fields()) 47 members = (f.name for f in cls.all_fields())
44 kwargs = {m: getattr(entity, m) for m in members if not m in overrides} 48 kwargs = {m: getattr(entity, m) for m in members if not m in overrides}
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 inputs_ref = _ndb_to_rpc( 122 inputs_ref = _ndb_to_rpc(
119 swarming_rpcs.FilesRef, entity.properties.inputs_ref) 123 swarming_rpcs.FilesRef, entity.properties.inputs_ref)
120 124
121 props = entity.properties 125 props = entity.properties
122 properties = _ndb_to_rpc( 126 properties = _ndb_to_rpc(
123 swarming_rpcs.TaskProperties, 127 swarming_rpcs.TaskProperties,
124 props, 128 props,
125 caches=[_ndb_to_rpc(swarming_rpcs.CacheEntry, c) for c in props.caches], 129 caches=[_ndb_to_rpc(swarming_rpcs.CacheEntry, c) for c in props.caches],
126 cipd_input=cipd_input, 130 cipd_input=cipd_input,
127 secret_bytes='<REDACTED>' if props.has_secret_bytes else None, 131 secret_bytes='<REDACTED>' if props.has_secret_bytes else None,
128 dimensions=_string_pairs_from_dict(props.dimensions), 132 dimensions=_string_pairs_from_list_of_tuples(props.dimensions),
129 env=_string_pairs_from_dict(props.env), 133 env=_string_pairs_from_dict(props.env),
130 inputs_ref=inputs_ref) 134 inputs_ref=inputs_ref)
131 135
132 return _ndb_to_rpc( 136 return _ndb_to_rpc(
133 swarming_rpcs.TaskRequest, 137 swarming_rpcs.TaskRequest,
134 entity, 138 entity,
135 authenticated=entity.authenticated.to_bytes(), 139 authenticated=entity.authenticated.to_bytes(),
136 properties=properties) 140 properties=properties)
137 141
138 142
(...skipping 25 matching lines...) Expand all
164 ]) 168 ])
165 169
166 inputs_ref = None 170 inputs_ref = None
167 if props.inputs_ref: 171 if props.inputs_ref:
168 inputs_ref = _rpc_to_ndb(task_request.FilesRef, props.inputs_ref) 172 inputs_ref = _rpc_to_ndb(task_request.FilesRef, props.inputs_ref)
169 173
170 secret_bytes = None 174 secret_bytes = None
171 if props.secret_bytes: 175 if props.secret_bytes:
172 secret_bytes = task_request.SecretBytes(secret_bytes=props.secret_bytes) 176 secret_bytes = task_request.SecretBytes(secret_bytes=props.secret_bytes)
173 177
174 if len(set(i.key for i in props.dimensions)) != len(props.dimensions): 178 # keys with ':' would corrupt the data. Rest of validation is done in
175 raise ValueError('same dimension key cannot be specified twice') 179 # TaskProperties.
180 if any(':' in i.key for i in props.dimensions):
181 raise ValueError('dimension key cannot contain ":"')
182 # Repeated keys would be lost. Rest of validation is done in TaskProperties.
176 if len(set(i.key for i in props.env)) != len(props.env): 183 if len(set(i.key for i in props.env)) != len(props.env):
177 raise ValueError('same environment variable key cannot be specified twice') 184 raise ValueError('same environment variable key cannot be specified twice')
178 185
179 properties = _rpc_to_ndb( 186 properties = _rpc_to_ndb(
180 task_request.TaskProperties, 187 task_request.TaskProperties,
181 props, 188 props,
182 caches=[_rpc_to_ndb(task_request.CacheEntry, c) for c in props.caches], 189 caches=[_rpc_to_ndb(task_request.CacheEntry, c) for c in props.caches],
183 cipd_input=cipd_input, 190 cipd_input=cipd_input,
184 # Passing command=None is supported at API level but not at NDB level. 191 # Passing command=None is supported at API level but not at NDB level.
185 command=props.command or [], 192 command=props.command or [],
186 has_secret_bytes=secret_bytes is not None, 193 has_secret_bytes=secret_bytes is not None,
187 secret_bytes=None, # ignore this, it's handled out of band 194 secret_bytes=None, # ignore this, it's handled out of band
188 dimensions=None, 195 dimensions=None,
189 dimensions_dict={i.key: i.value for i in props.dimensions}, 196 dimensions_flat=sorted(
190 dimensions_flat=[], 197 u'%s:%s' % (i.key, i.value) for i in props.dimensions),
191 env={i.key: i.value for i in props.env}, 198 env={i.key: i.value for i in props.env},
192 inputs_ref=inputs_ref) 199 inputs_ref=inputs_ref)
193 200
194 req = _rpc_to_ndb( 201 req = _rpc_to_ndb(
195 task_request.TaskRequest, 202 task_request.TaskRequest,
196 msg, 203 msg,
197 created_ts=now, 204 created_ts=now,
198 expiration_ts=now+datetime.timedelta(seconds=msg.expiration_secs), 205 expiration_ts=now+datetime.timedelta(seconds=msg.expiration_secs),
199 # It is set in task_request.init_new_request(). 206 # It is set in task_request.init_new_request().
200 authenticated=None, 207 authenticated=None,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 kwargs['run_id'] = entity.task_id 264 kwargs['run_id'] = entity.task_id
258 else: 265 else:
259 assert entity.__class__ is task_result.TaskResultSummary, entity 266 assert entity.__class__ is task_result.TaskResultSummary, entity
260 kwargs['properties_hash'] = ( 267 kwargs['properties_hash'] = (
261 entity.properties_hash.encode('hex') 268 entity.properties_hash.encode('hex')
262 if entity.properties_hash else None) 269 if entity.properties_hash else None)
263 # This returns the right value for deduped tasks too. 270 # This returns the right value for deduped tasks too.
264 k = entity.run_result_key 271 k = entity.run_result_key
265 kwargs['run_id'] = task_pack.pack_run_result_key(k) if k else None 272 kwargs['run_id'] = task_pack.pack_run_result_key(k) if k else None
266 return _ndb_to_rpc(swarming_rpcs.TaskResult, entity, **kwargs) 273 return _ndb_to_rpc(swarming_rpcs.TaskResult, entity, **kwargs)
OLDNEW
« no previous file with comments | « appengine/swarming/local_smoke_test.py ('k') | appengine/swarming/server/task_queues.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698