| 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 |