| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package main | 5 package main |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "errors" | 9 "errors" |
| 10 "flag" | 10 "flag" |
| 11 "fmt" | 11 "fmt" |
| 12 "os" | 12 "os" |
| 13 "time" | 13 "time" |
| 14 | 14 |
| 15 "github.com/golang/protobuf/proto" | 15 "github.com/golang/protobuf/proto" |
| 16 "github.com/luci/luci-go/client/logdog/annotee" | 16 "github.com/luci/luci-go/client/logdog/annotee" |
| 17 "github.com/luci/luci-go/client/logdog/annotee/executor" | 17 "github.com/luci/luci-go/client/logdog/annotee/executor" |
| 18 "github.com/luci/luci-go/client/logdog/butlerlib/bootstrap" | 18 "github.com/luci/luci-go/client/logdog/butlerlib/bootstrap" |
| 19 "github.com/luci/luci-go/client/logdog/butlerlib/streamclient" | 19 "github.com/luci/luci-go/client/logdog/butlerlib/streamclient" |
| 20 "github.com/luci/luci-go/client/logdog/butlerlib/streamproto" | 20 "github.com/luci/luci-go/client/logdog/butlerlib/streamproto" |
| 21 "github.com/luci/luci-go/common/clock/clockflag" | 21 "github.com/luci/luci-go/common/clock/clockflag" |
| 22 "github.com/luci/luci-go/common/config" |
| 22 "github.com/luci/luci-go/common/logdog/types" | 23 "github.com/luci/luci-go/common/logdog/types" |
| 23 log "github.com/luci/luci-go/common/logging" | 24 log "github.com/luci/luci-go/common/logging" |
| 24 "github.com/luci/luci-go/common/logging/gologger" | 25 "github.com/luci/luci-go/common/logging/gologger" |
| 25 "golang.org/x/net/context" | 26 "golang.org/x/net/context" |
| 26 ) | 27 ) |
| 27 | 28 |
| 28 const ( | 29 const ( |
| 29 // configErrorReturnCode is returned when there is an error with Annotee
's | 30 // configErrorReturnCode is returned when there is an error with Annotee
's |
| 30 // command-line configuration. | 31 // command-line configuration. |
| 31 configErrorReturnCode = 2 | 32 configErrorReturnCode = 2 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 50 type application struct { | 51 type application struct { |
| 51 context.Context | 52 context.Context |
| 52 | 53 |
| 53 annotate annotationMode | 54 annotate annotationMode |
| 54 jsonArgsPath string | 55 jsonArgsPath string |
| 55 butlerStreamServer string | 56 butlerStreamServer string |
| 56 tee bool | 57 tee bool |
| 57 printSummary bool | 58 printSummary bool |
| 58 testingDir string | 59 testingDir string |
| 59 annotationInterval clockflag.Duration | 60 annotationInterval clockflag.Duration |
| 61 project config.ProjectName |
| 60 nameBase streamproto.StreamNameFlag | 62 nameBase streamproto.StreamNameFlag |
| 61 prefix streamproto.StreamNameFlag | 63 prefix streamproto.StreamNameFlag |
| 62 logdogHost string | 64 logdogHost string |
| 63 | 65 |
| 64 bootstrap *bootstrap.Bootstrap | 66 bootstrap *bootstrap.Bootstrap |
| 65 } | 67 } |
| 66 | 68 |
| 67 func (a *application) addToFlagSet(fs *flag.FlagSet) { | 69 func (a *application) addToFlagSet(fs *flag.FlagSet) { |
| 68 fs.StringVar(&a.jsonArgsPath, "json-args-path", "", | 70 fs.StringVar(&a.jsonArgsPath, "json-args-path", "", |
| 69 "If specified, this is a JSON file containing the full command t
o run as an "+ | 71 "If specified, this is a JSON file containing the full command t
o run as an "+ |
| 70 "array of strings.") | 72 "array of strings.") |
| 71 fs.Var(&a.annotate, "annotate", | 73 fs.Var(&a.annotate, "annotate", |
| 72 "Annotation handling mode. Options are: "+annotationFlagEnum.Cho
ices()) | 74 "Annotation handling mode. Options are: "+annotationFlagEnum.Cho
ices()) |
| 73 fs.StringVar(&a.butlerStreamServer, "butler-stream-server", "", | 75 fs.StringVar(&a.butlerStreamServer, "butler-stream-server", "", |
| 74 "The Butler stream server location. If empty, Annotee will check
for Butler "+ | 76 "The Butler stream server location. If empty, Annotee will check
for Butler "+ |
| 75 "bootstrapping and extract the stream server from that."
) | 77 "bootstrapping and extract the stream server from that."
) |
| 76 fs.BoolVar(&a.tee, "tee", true, | 78 fs.BoolVar(&a.tee, "tee", true, |
| 77 "Tee the bootstrapped process' STDOUT/STDERR streams.") | 79 "Tee the bootstrapped process' STDOUT/STDERR streams.") |
| 78 fs.BoolVar(&a.printSummary, "print-summary", true, | 80 fs.BoolVar(&a.printSummary, "print-summary", true, |
| 79 "Print the annotation protobufs that were emitted at the end.") | 81 "Print the annotation protobufs that were emitted at the end.") |
| 80 fs.StringVar(&a.testingDir, "testing-dir", "", | 82 fs.StringVar(&a.testingDir, "testing-dir", "", |
| 81 "Rather than coupling to a Butler instance, output generated ann
otations "+ | 83 "Rather than coupling to a Butler instance, output generated ann
otations "+ |
| 82 "and streams to this directory.") | 84 "and streams to this directory.") |
| 83 fs.Var(&a.annotationInterval, "annotation-interval", | 85 fs.Var(&a.annotationInterval, "annotation-interval", |
| 84 "Buffer annotation updates for this amount of time. <=0 sends ev
ery update.") | 86 "Buffer annotation updates for this amount of time. <=0 sends ev
ery update.") |
| 87 fs.Var(&a.project, "project", "The log prefix's project name (required).
") |
| 85 fs.Var(&a.nameBase, "name-base", "Base stream name to prepend to generat
ed names.") | 88 fs.Var(&a.nameBase, "name-base", "Base stream name to prepend to generat
ed names.") |
| 86 fs.Var(&a.prefix, "prefix", "The log stream prefix. If missing, one will
be inferred from bootstrap.") | 89 fs.Var(&a.prefix, "prefix", "The log stream prefix. If missing, one will
be inferred from bootstrap.") |
| 87 fs.StringVar(&a.logdogHost, "logdog-host", "", | 90 fs.StringVar(&a.logdogHost, "logdog-host", "", |
| 88 "LogDog Coordinator host name. If supplied, log viewing links wi
ll be generated.") | 91 "LogDog Coordinator host name. If supplied, log viewing links wi
ll be generated.") |
| 89 } | 92 } |
| 90 | 93 |
| 91 func (a *application) loadJSONArgs() ([]string, error) { | 94 func (a *application) loadJSONArgs() ([]string, error) { |
| 92 fd, err := os.Open(a.jsonArgsPath) | 95 fd, err := os.Open(a.jsonArgsPath) |
| 93 if err != nil { | 96 if err != nil { |
| 94 return nil, err | 97 return nil, err |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 if err != nil { | 154 if err != nil { |
| 152 log.WithError(err).Errorf(a, "Failed to get stream client instan
ce.") | 155 log.WithError(err).Errorf(a, "Failed to get stream client instan
ce.") |
| 153 return configErrorReturnCode | 156 return configErrorReturnCode |
| 154 } | 157 } |
| 155 | 158 |
| 156 prefix := types.StreamName(a.prefix) | 159 prefix := types.StreamName(a.prefix) |
| 157 if prefix == "" && a.bootstrap != nil { | 160 if prefix == "" && a.bootstrap != nil { |
| 158 prefix = a.bootstrap.Prefix | 161 prefix = a.bootstrap.Prefix |
| 159 } | 162 } |
| 160 | 163 |
| 164 // TODO(dnj): Require project attribute. |
| 165 if a.project == "" { |
| 166 a.project = a.bootstrap.Project |
| 167 } |
| 168 |
| 161 args = fs.Args() | 169 args = fs.Args() |
| 162 if a.jsonArgsPath != "" { | 170 if a.jsonArgsPath != "" { |
| 163 if len(args) > 0 { | 171 if len(args) > 0 { |
| 164 log.Fields{ | 172 log.Fields{ |
| 165 "commandLineArgs": args, | 173 "commandLineArgs": args, |
| 166 "jsonArgsPath": a.jsonArgsPath, | 174 "jsonArgsPath": a.jsonArgsPath, |
| 167 }.Errorf(a, "Cannot specify both JSON and command-line a
rguments.") | 175 }.Errorf(a, "Cannot specify both JSON and command-line a
rguments.") |
| 168 return configErrorReturnCode | 176 return configErrorReturnCode |
| 169 } | 177 } |
| 170 | 178 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 181 log.Errorf(a, "No command-line arguments were supplied.") | 189 log.Errorf(a, "No command-line arguments were supplied.") |
| 182 return configErrorReturnCode | 190 return configErrorReturnCode |
| 183 } | 191 } |
| 184 | 192 |
| 185 // Translate "<=0" flag option to Processor's "0", indicating that every | 193 // Translate "<=0" flag option to Processor's "0", indicating that every |
| 186 // update should be sent. | 194 // update should be sent. |
| 187 if a.annotationInterval < 0 { | 195 if a.annotationInterval < 0 { |
| 188 a.annotationInterval = 0 | 196 a.annotationInterval = 0 |
| 189 } | 197 } |
| 190 | 198 |
| 199 // Initialize our link generator, if we can. |
| 200 linkGen := &coordinatorLinkGenerator{ |
| 201 base: types.StreamName(a.nameBase), |
| 202 project: a.project, |
| 203 prefix: prefix, |
| 204 } |
| 205 if !linkGen.canGenerateLinks() { |
| 206 linkGen = nil |
| 207 } |
| 208 |
| 191 e := executor.Executor{ | 209 e := executor.Executor{ |
| 192 Options: annotee.Options{ | 210 Options: annotee.Options{ |
| 193 Base: types.StreamName(a.nameBase), | |
| 194 Prefix: prefix, | |
| 195 Client: client, | 211 Client: client, |
| 212 LinkGenerator: linkGen, |
| 196 MetadataUpdateInterval: time.Duration(a.annotationInterv
al), | 213 MetadataUpdateInterval: time.Duration(a.annotationInterv
al), |
| 197 LogDogHost: a.logdogHost, | |
| 198 }, | 214 }, |
| 199 | 215 |
| 200 Annotate: executor.AnnotationMode(a.annotate), | 216 Annotate: executor.AnnotationMode(a.annotate), |
| 201 Stdin: os.Stdin, | 217 Stdin: os.Stdin, |
| 202 } | 218 } |
| 203 if a.tee { | 219 if a.tee { |
| 204 e.TeeStdout = os.Stdout | 220 e.TeeStdout = os.Stdout |
| 205 e.TeeStderr = os.Stderr | 221 e.TeeStderr = os.Stderr |
| 206 } | 222 } |
| 207 if err := e.Run(a, args); err != nil { | 223 if err := e.Run(a, args); err != nil { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 221 | 237 |
| 222 if !e.Executed() { | 238 if !e.Executed() { |
| 223 return runtimeErrorReturnCode | 239 return runtimeErrorReturnCode |
| 224 } | 240 } |
| 225 return e.ReturnCode() | 241 return e.ReturnCode() |
| 226 } | 242 } |
| 227 | 243 |
| 228 func main() { | 244 func main() { |
| 229 os.Exit(mainImpl(os.Args[1:])) | 245 os.Exit(mainImpl(os.Args[1:])) |
| 230 } | 246 } |
| OLD | NEW |