OLD | NEW |
1 // Copyright 2017 The LUCI Authors. All rights reserved. | 1 // Copyright 2017 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 package swarming | 5 package swarming |
6 | 6 |
7 import ( | 7 import ( |
8 "strconv" | 8 "strconv" |
9 "strings" | 9 "strings" |
10 "unicode/utf8" | 10 "unicode/utf8" |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 switch { | 213 switch { |
214 case luciProject == "": | 214 case luciProject == "": |
215 return nil, errors.New("no 'luci_project' tag") | 215 return nil, errors.New("no 'luci_project' tag") |
216 case logLocation == "": | 216 case logLocation == "": |
217 return nil, errors.New("no 'log_location' tag") | 217 return nil, errors.New("no 'log_location' tag") |
218 } | 218 } |
219 | 219 |
220 // Gather our Swarming task template parameters and perform a substituti
on. | 220 // Gather our Swarming task template parameters and perform a substituti
on. |
221 runID, err := getRunID(taskID, tryNumber) | 221 runID, err := getRunID(taskID, tryNumber) |
222 if err != nil { | 222 if err != nil { |
223 » » return nil, errors.Annotate(err).Err() | 223 » » return nil, errors.Annotate(err, "").Err() |
224 } | 224 } |
225 p := tasktemplate.Params{ | 225 p := tasktemplate.Params{ |
226 SwarmingRunID: runID, | 226 SwarmingRunID: runID, |
227 } | 227 } |
228 if logLocation, err = p.Resolve(logLocation); err != nil { | 228 if logLocation, err = p.Resolve(logLocation); err != nil { |
229 » » return nil, errors.Annotate(err).Reason("failed to resolve swarm
ing task templating in 'log_location'").Err() | 229 » » return nil, errors.Annotate(err, "failed to resolve swarming tas
k templating in 'log_location'").Err() |
230 } | 230 } |
231 | 231 |
232 addr, err := types.ParseURL(logLocation) | 232 addr, err := types.ParseURL(logLocation) |
233 if err != nil { | 233 if err != nil { |
234 » » return nil, errors.Annotate(err).Reason("could not parse LogDog
stream from location").Err() | 234 » » return nil, errors.Annotate(err, "could not parse LogDog stream
from location").Err() |
235 } | 235 } |
236 | 236 |
237 // The LogDog stream's project should match the LUCI project. | 237 // The LogDog stream's project should match the LUCI project. |
238 if string(addr.Project) != luciProject { | 238 if string(addr.Project) != luciProject { |
239 » » return nil, errors.Reason("stream project %(streamProject)q does
n't match LUCI project %(luciProject)q"). | 239 » » return nil, errors.Reason("stream project %q doesn't match LUCI
project %q", addr.Project, luciProject).Err() |
240 » » » D("luciProject", luciProject). | |
241 » » » D("streamProject", addr.Project). | |
242 » » » Err() | |
243 } | 240 } |
244 | 241 |
245 return addr, nil | 242 return addr, nil |
246 } | 243 } |
247 | 244 |
248 // getRunID converts a Swarming task ID and try number into a Swarming Run ID. | 245 // getRunID converts a Swarming task ID and try number into a Swarming Run ID. |
249 // | 246 // |
250 // The run ID is a permutation of the last four bits of the Swarming Task ID. | 247 // The run ID is a permutation of the last four bits of the Swarming Task ID. |
251 // Therefore, we chop it off of the string, mutate it, and then add it back. | 248 // Therefore, we chop it off of the string, mutate it, and then add it back. |
252 // | 249 // |
253 // TODO(dnj): Replace this with Swarming API call once finished. | 250 // TODO(dnj): Replace this with Swarming API call once finished. |
254 func getRunID(taskID string, tryNumber int64) (string, error) { | 251 func getRunID(taskID string, tryNumber int64) (string, error) { |
255 // Slice off the last character form the task ID. | 252 // Slice off the last character form the task ID. |
256 if len(taskID) == 0 { | 253 if len(taskID) == 0 { |
257 return "", errors.New("swarming task ID is empty") | 254 return "", errors.New("swarming task ID is empty") |
258 } | 255 } |
259 | 256 |
260 // Parse "tryNumber" as a hex string. | 257 // Parse "tryNumber" as a hex string. |
261 if tryNumber < 0 || tryNumber > 0x0F { | 258 if tryNumber < 0 || tryNumber > 0x0F { |
262 » » return "", errors.Reason("try number %(try)d exceeds 4 bits"). | 259 » » return "", errors.Reason("try number %d exceeds 4 bits", tryNumb
er).Err() |
263 » » » D("try", tryNumber). | |
264 » » » Err() | |
265 } | 260 } |
266 | 261 |
267 lastChar, lastCharSize := utf8.DecodeLastRuneInString(taskID) | 262 lastChar, lastCharSize := utf8.DecodeLastRuneInString(taskID) |
268 v, err := strconv.ParseUint(string(lastChar), 16, 8) | 263 v, err := strconv.ParseUint(string(lastChar), 16, 8) |
269 if err != nil { | 264 if err != nil { |
270 » » return "", errors.Annotate(err).Reason("failed to parse hex from
rune: %(rune)r"). | 265 » » return "", errors.Annotate(err, "failed to parse hex from rune:
%r", lastChar).Err() |
271 » » » D("rune", lastChar). | |
272 » » » Err() | |
273 } | 266 } |
274 | 267 |
275 return taskID[:len(taskID)-lastCharSize] + strconv.FormatUint((v|uint64(
tryNumber)), 16), nil | 268 return taskID[:len(taskID)-lastCharSize] + strconv.FormatUint((v|uint64(
tryNumber)), 16), nil |
276 } | 269 } |
OLD | NEW |