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

Unified Diff: milo/appengine/swarming/buildinfo.go

Issue 2944983003: [milo] {buildbucket,buildbot,swarming,logdog} -> backends/*. (Closed)
Patch Set: fix the tests 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « milo/appengine/swarming/build_test.go ('k') | milo/appengine/swarming/buildinfo_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: milo/appengine/swarming/buildinfo.go
diff --git a/milo/appengine/swarming/buildinfo.go b/milo/appengine/swarming/buildinfo.go
deleted file mode 100644
index 0f7361de3a18bfe998d54bbd1ca2c77006ae16bd..0000000000000000000000000000000000000000
--- a/milo/appengine/swarming/buildinfo.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2017 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-package swarming
-
-import (
- "strconv"
- "strings"
- "unicode/utf8"
-
- swarming "github.com/luci/luci-go/common/api/swarming/swarming/v1"
- "github.com/luci/luci-go/common/errors"
- "github.com/luci/luci-go/common/logging"
- miloProto "github.com/luci/luci-go/common/proto/milo"
- "github.com/luci/luci-go/grpc/grpcutil"
- "github.com/luci/luci-go/logdog/common/types"
- "github.com/luci/luci-go/luci_config/common/cfgtypes"
- milo "github.com/luci/luci-go/milo/api/proto"
- "github.com/luci/luci-go/swarming/tasktemplate"
-
- "golang.org/x/net/context"
-)
-
-// BuildInfoProvider provides build information.
-//
-// In a production system, this will be completely defaults. For testing, the
-// various services and data sources may be substituted for testing stubs.
-type BuildInfoProvider struct {
- bl buildLoader
-
- // swarmingServiceFunc returns a swarmingService instance for the supplied
- // parameters.
- //
- // If nil, a production fetcher will be generated.
- swarmingServiceFunc func(c context.Context, host string) (swarmingService, error)
-}
-
-func (p *BuildInfoProvider) newSwarmingService(c context.Context, host string) (swarmingService, error) {
- if p.swarmingServiceFunc == nil {
- return newProdService(c, host)
- }
- return p.swarmingServiceFunc(c, host)
-}
-
-// GetBuildInfo resolves a Milo protobuf Step for a given Swarming task.
-func (p *BuildInfoProvider) GetBuildInfo(c context.Context, req *milo.BuildInfoRequest_Swarming,
- projectHint cfgtypes.ProjectName) (*milo.BuildInfoResponse, error) {
-
- // Load the Swarming task (no log content).
- sf, err := p.newSwarmingService(c, req.Host)
- if err != nil {
- logging.WithError(err).Errorf(c, "Failed to create Swarming fetcher.")
- return nil, grpcutil.Internal
- }
-
- // Use default Swarming host.
- host := sf.getHost()
- logging.Infof(c, "Loading build info for Swarming host %s, task %s.", host, req.Task)
-
- fetchParams := swarmingFetchParams{
- fetchReq: true,
- fetchRes: true,
- }
- fr, err := swarmingFetch(c, sf, req.Task, fetchParams)
- if err != nil {
- if err == errNotMiloJob {
- logging.Warningf(c, "User requested nonexistent task or does not have permissions.")
- return nil, grpcutil.NotFound
- }
-
- logging.WithError(err).Errorf(c, "Failed to load Swarming task.")
- return nil, grpcutil.Internal
- }
-
- // Determine the LogDog annotation stream path for this Swarming task.
- //
- // On failure, will return a gRPC error.
- stream, err := resolveLogDogAnnotations(c, fr.req, projectHint, host, req.Task, fr.res.TryNumber)
- if err != nil {
- logging.WithError(err).Warningf(c, "Failed to get annotation stream parameters.")
- return nil, err
- }
-
- logging.Fields{
- "host": stream.Host,
- "project": stream.Project,
- "path": stream.Path,
- }.Infof(c, "Resolved LogDog annotation stream.")
-
- as, err := p.bl.newEmptyAnnotationStream(c, stream)
- if err != nil {
- logging.WithError(err).Errorf(c, "Failed to create LogDog annotation stream.")
- return nil, grpcutil.Internal
- }
-
- // Fetch LogDog annotation stream data.
- step, err := as.Fetch(c)
- if err != nil {
- logging.WithError(err).Warningf(c, "Failed to load annotation stream.")
- return nil, grpcutil.Internal
- }
-
- // Add Swarming task parameters to the Milo step.
- if err := addTaskToMiloStep(c, sf.getHost(), fr.res, step); err != nil {
- return nil, err
- }
-
- prefix, name := as.Path.Split()
- return &milo.BuildInfoResponse{
- Project: string(as.Project),
- Step: step,
- AnnotationStream: &miloProto.LogdogStream{
- Server: as.Client.Host,
- Prefix: string(prefix),
- Name: string(name),
- },
- }, nil
-}
-
-// resolveLogDogAnnotations returns a configured AnnotationStream given the input
-// parameters.
-//
-// This will return a gRPC error on failure.
-//
-// This function is messy and implementation-specific. That's the point of this
-// endpoint, though. All of the nastiness here should be replaced with something
-// more elegant once that becomes available. In the meantime...
-func resolveLogDogAnnotations(c context.Context, sr *swarming.SwarmingRpcsTaskRequest, projectHint cfgtypes.ProjectName,
- host, taskID string, tryNumber int64) (*types.StreamAddr, error) {
-
- // Try and resolve from explicit tags (preferred).
- tags := swarmingTags(sr.Tags)
- addr, err := resolveLogDogStreamAddrFromTags(tags, taskID, tryNumber)
- if err == nil {
- return addr, nil
- }
- logging.WithError(err).Debugf(c, "Could not resolve stream address from tags.")
-
- // If this is a Kitchen command, maybe we can infer our LogDog project from
- // the command-line.
- if sr.Properties == nil {
- logging.Warningf(c, "No request properties, can't infer annotation stream path.")
- return nil, grpcutil.NotFound
- }
-
- addr = &types.StreamAddr{}
- var isKitchen bool
- if addr.Project, isKitchen = getLogDogProjectFromKitchen(sr.Properties.Command); !isKitchen {
- logging.Warningf(c, "Not a Kitchen CLI, can't infer annotation stream path.")
- return nil, grpcutil.NotFound
- }
-
- if addr.Project == "" {
- addr.Project = projectHint
- }
- if addr.Project == "" {
- logging.Warningf(c, "Don't know how to get annotation stream path.")
- return nil, grpcutil.NotFound
- }
-
- // This is a Kitchen run, and it has a project! Construct the annotation
- // stream path.
- //
- // This is an implementation of:
- // https://chromium.googlesource.com/infra/infra/+/a7032e3e240d4b81a1912bfaf29a20d02f665cc1/go/src/infra/tools/kitchen/cook_logdog.go#129
- runID, err := getRunID(taskID, tryNumber)
- if err != nil {
- logging.Fields{
- logging.ErrorKey: err,
- "taskID": taskID,
- "tryNumber": tryNumber,
- }.Errorf(c, "Failed to get Run ID for task/try.")
- return nil, grpcutil.Internal
- }
-
- prefix, err := types.MakeStreamName("", "swarm", host, runID)
- if err != nil {
- logging.WithError(err).Errorf(c, "Failed to generate Swarming prefix.")
- return nil, grpcutil.Internal
- }
- addr.Path = prefix.Join("annotations")
- return addr, nil
-}
-
-func getLogDogProjectFromKitchen(cmd []string) (proj cfgtypes.ProjectName, isKitchen bool) {
- // Is this a Kitchen command?
- switch {
- case len(cmd) == 0:
- return
- case !strings.HasPrefix(cmd[0], "kitchen"):
- return
- }
- isKitchen = true
- cmd = cmd[1:]
-
- // Scan through for the "-logdog-project" argument.
- for i, arg := range cmd {
- if arg == "-logdog-project" {
- if i < len(cmd)-2 {
- proj = cfgtypes.ProjectName(cmd[i+1])
- return
- }
- break
- }
- }
- return
-}
-
-func resolveLogDogStreamAddrFromTags(tags map[string]string, taskID string, tryNumber int64) (*types.StreamAddr, error) {
- // If we don't have a LUCI project, abort.
- luciProject, logLocation := tags["luci_project"], tags["log_location"]
- switch {
- case luciProject == "":
- return nil, errors.New("no 'luci_project' tag")
- case logLocation == "":
- return nil, errors.New("no 'log_location' tag")
- }
-
- // Gather our Swarming task template parameters and perform a substitution.
- runID, err := getRunID(taskID, tryNumber)
- if err != nil {
- return nil, errors.Annotate(err).Err()
- }
- p := tasktemplate.Params{
- SwarmingRunID: runID,
- }
- if logLocation, err = p.Resolve(logLocation); err != nil {
- return nil, errors.Annotate(err).Reason("failed to resolve swarming task templating in 'log_location'").Err()
- }
-
- addr, err := types.ParseURL(logLocation)
- if err != nil {
- return nil, errors.Annotate(err).Reason("could not parse LogDog stream from location").Err()
- }
-
- // The LogDog stream's project should match the LUCI project.
- if string(addr.Project) != luciProject {
- return nil, errors.Reason("stream project %(streamProject)q doesn't match LUCI project %(luciProject)q").
- D("luciProject", luciProject).
- D("streamProject", addr.Project).
- Err()
- }
-
- return addr, nil
-}
-
-// getRunID converts a Swarming task ID and try number into a Swarming Run ID.
-//
-// The run ID is a permutation of the last four bits of the Swarming Task ID.
-// Therefore, we chop it off of the string, mutate it, and then add it back.
-//
-// TODO(dnj): Replace this with Swarming API call once finished.
-func getRunID(taskID string, tryNumber int64) (string, error) {
- // Slice off the last character form the task ID.
- if len(taskID) == 0 {
- return "", errors.New("swarming task ID is empty")
- }
-
- // Parse "tryNumber" as a hex string.
- if tryNumber < 0 || tryNumber > 0x0F {
- return "", errors.Reason("try number %(try)d exceeds 4 bits").
- D("try", tryNumber).
- Err()
- }
-
- lastChar, lastCharSize := utf8.DecodeLastRuneInString(taskID)
- v, err := strconv.ParseUint(string(lastChar), 16, 8)
- if err != nil {
- return "", errors.Annotate(err).Reason("failed to parse hex from rune: %(rune)r").
- D("rune", lastChar).
- Err()
- }
-
- return taskID[:len(taskID)-lastCharSize] + strconv.FormatUint((v|uint64(tryNumber)), 16), nil
-}
« no previous file with comments | « milo/appengine/swarming/build_test.go ('k') | milo/appengine/swarming/buildinfo_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698