| OLD | NEW |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 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 main | 5 package main |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "flag" |
| 9 "fmt" |
| 8 "io" | 10 "io" |
| 9 "os/exec" | 11 "os/exec" |
| 10 "sync" | 12 "sync" |
| 11 "time" | 13 "time" |
| 12 | 14 |
| 13 "github.com/luci/luci-go/client/logdog/annotee" | 15 "github.com/luci/luci-go/client/logdog/annotee" |
| 14 "github.com/luci/luci-go/client/logdog/annotee/annotation" | 16 "github.com/luci/luci-go/client/logdog/annotee/annotation" |
| 15 "github.com/luci/luci-go/client/logdog/butler" | 17 "github.com/luci/luci-go/client/logdog/butler" |
| 16 "github.com/luci/luci-go/client/logdog/butler/bootstrap" | 18 "github.com/luci/luci-go/client/logdog/butler/bootstrap" |
| 17 "github.com/luci/luci-go/client/logdog/butler/output" | 19 "github.com/luci/luci-go/client/logdog/butler/output" |
| 18 fileOut "github.com/luci/luci-go/client/logdog/butler/output/file" | 20 fileOut "github.com/luci/luci-go/client/logdog/butler/output/file" |
| 19 out "github.com/luci/luci-go/client/logdog/butler/output/logdog" | 21 out "github.com/luci/luci-go/client/logdog/butler/output/logdog" |
| 20 "github.com/luci/luci-go/client/logdog/butlerlib/streamclient" | 22 "github.com/luci/luci-go/client/logdog/butlerlib/streamclient" |
| 21 "github.com/luci/luci-go/common/auth" | 23 "github.com/luci/luci-go/common/auth" |
| 22 "github.com/luci/luci-go/common/config" | 24 "github.com/luci/luci-go/common/config" |
| 23 "github.com/luci/luci-go/common/ctxcmd" | 25 "github.com/luci/luci-go/common/ctxcmd" |
| 24 "github.com/luci/luci-go/common/environ" | 26 "github.com/luci/luci-go/common/environ" |
| 25 "github.com/luci/luci-go/common/errors" | 27 "github.com/luci/luci-go/common/errors" |
| 28 "github.com/luci/luci-go/common/logdog/types" |
| 26 log "github.com/luci/luci-go/common/logging" | 29 log "github.com/luci/luci-go/common/logging" |
| 27 | 30 |
| 28 "github.com/golang/protobuf/proto" | 31 "github.com/golang/protobuf/proto" |
| 29 "golang.org/x/net/context" | 32 "golang.org/x/net/context" |
| 30 ) | 33 ) |
| 31 | 34 |
| 35 type cookLogDogParams struct { |
| 36 host string |
| 37 project string |
| 38 prefix types.StreamName |
| 39 annotee bool |
| 40 filePath string |
| 41 } |
| 42 |
| 43 func (p *cookLogDogParams) addFlags(fs *flag.FlagSet) { |
| 44 fs.StringVar( |
| 45 &p.host, |
| 46 "logdog-host", |
| 47 "", |
| 48 "The name of the LogDog host.") |
| 49 fs.StringVar( |
| 50 &p.project, |
| 51 "logdog-project", |
| 52 "", |
| 53 "The name of the LogDog project to log into. Projects have diffe
rent ACL sets, "+ |
| 54 "so choose this appropriately.") |
| 55 fs.Var( |
| 56 &p.prefix, |
| 57 "logdog-prefix", |
| 58 "The LogDog stream Prefix to use. If empty, one will be construc
ted from the Swarming "+ |
| 59 "task parameters (found in enviornment).") |
| 60 fs.BoolVar( |
| 61 &p.annotee, |
| 62 "logdog-enable-annotee", |
| 63 true, |
| 64 "Process bootstrap STDOUT/STDERR annotations through Annotee.") |
| 65 fs.StringVar( |
| 66 &p.filePath, |
| 67 "logdog-debug-out-file", |
| 68 "", |
| 69 "If specified, write all generated logs to this path instead of
sending them.") |
| 70 } |
| 71 |
| 72 func (p *cookLogDogParams) active() bool { |
| 73 return p.host != "" || p.project != "" || p.prefix != "" |
| 74 } |
| 75 |
| 76 func (p *cookLogDogParams) validate() error { |
| 77 if p.project == "" { |
| 78 return fmt.Errorf("a LogDog project must be supplied (-logdog-pr
oject)") |
| 79 } |
| 80 return nil |
| 81 } |
| 82 |
| 83 func (p *cookLogDogParams) getPrefix(env environ.Env) (types.StreamName, error)
{ |
| 84 if p.prefix != "" { |
| 85 return p.prefix, nil |
| 86 } |
| 87 |
| 88 // Construct our LogDog prefix from the Swarming task parameters. |
| 89 host, _ := env.Get("SWARMING_SERVER") |
| 90 if host == "" { |
| 91 return "", errors.Reason("missing or empty SWARMING_SERVER").Err
() |
| 92 } |
| 93 taskID, _ := env.Get("SWARMING_TASK_ID") |
| 94 if taskID == "" { |
| 95 return "", errors.Reason("missing or empty SWARMING_TASK_ID").Er
r() |
| 96 } |
| 97 |
| 98 return types.MakeStreamName("", "swarm", host, taskID) |
| 99 } |
| 100 |
| 32 // runWithLogdogButler rus the supplied command through the a LogDog Butler | 101 // runWithLogdogButler rus the supplied command through the a LogDog Butler |
| 33 // engine instance. This involves: | 102 // engine instance. This involves: |
| 34 // - Determine a LogDog Prefix. | 103 // - Determine a LogDog Prefix. |
| 35 // - Configuring / setting up the Butler. | 104 // - Configuring / setting up the Butler. |
| 36 // - Initiating a LogDog Pub/Sub Output, registering with remote server. | 105 // - Initiating a LogDog Pub/Sub Output, registering with remote server. |
| 37 // - Running the recipe process. | 106 // - Running the recipe process. |
| 38 // - Optionally, hook its output streams up through an Annotee processor. | 107 // - Optionally, hook its output streams up through an Annotee processor. |
| 39 // - Otherwise, wait for the process to finish. | 108 // - Otherwise, wait for the process to finish. |
| 40 // - Shut down the Butler instance. | 109 // - Shut down the Butler instance. |
| 41 func (c *cookRun) runWithLogdogButler(ctx context.Context, cmd *exec.Cmd) (rc in
t, err error) { | 110 func (c *cookRun) runWithLogdogButler(ctx context.Context, cmd *exec.Cmd) (rc in
t, err error) { |
| 42 » _ = auth.Authenticator{} | 111 » // Get our task's environment. |
| 112 » var env environ.Env |
| 113 » if cmd.Env != nil { |
| 114 » » env = environ.New(cmd.Env) |
| 115 » } else { |
| 116 » » env = environ.System() |
| 117 » } |
| 118 |
| 119 » prefix, err := c.logdog.getPrefix(env) |
| 120 » if err != nil { |
| 121 » » return 0, errors.Annotate(err).Reason("failed to get LogDog pref
ix").Err() |
| 122 » } |
| 123 » log.Fields{ |
| 124 » » "prefix": prefix, |
| 125 » }.Infof(ctx, "Using LogDog prefix: %q", prefix) |
| 43 | 126 |
| 44 authenticator := auth.NewAuthenticator(ctx, auth.SilentLogin, auth.Optio
ns{ | 127 authenticator := auth.NewAuthenticator(ctx, auth.SilentLogin, auth.Optio
ns{ |
| 45 Scopes: out.Scopes(), | 128 Scopes: out.Scopes(), |
| 46 }) | 129 }) |
| 47 | 130 |
| 48 // Register and instantiate our LogDog Output. | 131 // Register and instantiate our LogDog Output. |
| 49 var o output.Output | 132 var o output.Output |
| 50 if c.logdog.filePath == "" { | 133 if c.logdog.filePath == "" { |
| 51 ocfg := out.Config{ | 134 ocfg := out.Config{ |
| 52 Auth: authenticator, | 135 Auth: authenticator, |
| 53 Host: c.logdog.host, | 136 Host: c.logdog.host, |
| 54 Project: config.ProjectName(c.logdog.project), | 137 Project: config.ProjectName(c.logdog.project), |
| 55 » » » Prefix: c.logdog.prefix, | 138 » » » Prefix: prefix, |
| 56 SourceInfo: []string{ | 139 SourceInfo: []string{ |
| 57 "Kitchen", | 140 "Kitchen", |
| 58 }, | 141 }, |
| 59 PublishContext: withNonCancel(ctx), | 142 PublishContext: withNonCancel(ctx), |
| 60 } | 143 } |
| 61 | 144 |
| 62 var err error | 145 var err error |
| 63 if o, err = ocfg.Register(ctx); err != nil { | 146 if o, err = ocfg.Register(ctx); err != nil { |
| 64 return 0, errors.Annotate(err).Reason("failed to create
LogDog Output instance").Err() | 147 return 0, errors.Annotate(err).Reason("failed to create
LogDog Output instance").Err() |
| 65 } | 148 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 94 err = ierr | 177 err = ierr |
| 95 } | 178 } |
| 96 } | 179 } |
| 97 }() | 180 }() |
| 98 | 181 |
| 99 // Wrap our incoming command in a CtxCmd. | 182 // Wrap our incoming command in a CtxCmd. |
| 100 proc := ctxcmd.CtxCmd{ | 183 proc := ctxcmd.CtxCmd{ |
| 101 Cmd: cmd, | 184 Cmd: cmd, |
| 102 } | 185 } |
| 103 | 186 |
| 104 var env environ.Env | |
| 105 if proc.Env != nil { | |
| 106 env = environ.New(proc.Env) | |
| 107 } else { | |
| 108 env = environ.System() | |
| 109 } | |
| 110 | |
| 111 // Augment our environment with Butler parameters. | 187 // Augment our environment with Butler parameters. |
| 112 bsEnv := bootstrap.Environment{ | 188 bsEnv := bootstrap.Environment{ |
| 113 Project: config.ProjectName(c.logdog.project), | 189 Project: config.ProjectName(c.logdog.project), |
| 114 Prefix: c.logdog.prefix, | 190 Prefix: c.logdog.prefix, |
| 115 } | 191 } |
| 116 bsEnv.Augment(env) | 192 bsEnv.Augment(env) |
| 117 proc.Env = env.Sorted() | 193 proc.Env = env.Sorted() |
| 118 | 194 |
| 119 // Build pipes for our STDOUT and STDERR streams. | 195 // Build pipes for our STDOUT and STDERR streams. |
| 120 stdout, err := proc.StdoutPipe() | 196 stdout, err := proc.StdoutPipe() |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 // callbackReadCloser invokes a callback method when closed. | 331 // callbackReadCloser invokes a callback method when closed. |
| 256 type callbackReadCloser struct { | 332 type callbackReadCloser struct { |
| 257 io.ReadCloser | 333 io.ReadCloser |
| 258 callback func() | 334 callback func() |
| 259 } | 335 } |
| 260 | 336 |
| 261 func (c *callbackReadCloser) Close() error { | 337 func (c *callbackReadCloser) Close() error { |
| 262 defer c.callback() | 338 defer c.callback() |
| 263 return c.ReadCloser.Close() | 339 return c.ReadCloser.Close() |
| 264 } | 340 } |
| OLD | NEW |