Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 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 cli |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "flag" | 8 "flag" |
| 9 "fmt" | 9 "fmt" |
| 10 "os" | 10 "os" |
| 11 "os/signal" | 11 "os/signal" |
| 12 "strings" | 12 "strings" |
| 13 "time" | 13 "time" |
| 14 | 14 |
| 15 "github.com/maruel/subcommands" | 15 "github.com/maruel/subcommands" |
| 16 "golang.org/x/net/context" | 16 "golang.org/x/net/context" |
| 17 | 17 |
| 18 "github.com/luci/luci-go/client/authcli" | 18 "github.com/luci/luci-go/client/authcli" |
| 19 "github.com/luci/luci-go/common/auth" | 19 "github.com/luci/luci-go/common/auth" |
| 20 "github.com/luci/luci-go/common/cli" | 20 "github.com/luci/luci-go/common/cli" |
| 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/config" |
| 23 log "github.com/luci/luci-go/common/logging" | 23 log "github.com/luci/luci-go/common/logging" |
| 24 "github.com/luci/luci-go/common/logging/gologger" | 24 "github.com/luci/luci-go/common/logging/gologger" |
| 25 "github.com/luci/luci-go/grpc/prpc" | 25 "github.com/luci/luci-go/grpc/prpc" |
| 26 "github.com/luci/luci-go/logdog/client/coordinator" | 26 "github.com/luci/luci-go/logdog/client/coordinator" |
| 27 "github.com/luci/luci-go/logdog/common/types" | 27 "github.com/luci/luci-go/logdog/common/types" |
| 28 ) | 28 ) |
| 29 | 29 |
| 30 func init() { | 30 func init() { |
| 31 prpc.DefaultUserAgent = "logdog CLI" | 31 prpc.DefaultUserAgent = "logdog CLI" |
| 32 } | 32 } |
| 33 | 33 |
| 34 // Parameters is the set of application parametesr that can be supplied. | |
| 35 type Parameters struct { | |
| 36 // Args is the command-line arguments. This should not include the comma nd name, | |
| 37 // args[0]. | |
| 38 Args []string | |
| 39 | |
| 40 // Host is the default host name. | |
| 41 Host string | |
| 42 } | |
| 43 | |
| 34 type application struct { | 44 type application struct { |
| 35 cli.Application | 45 cli.Application |
| 36 context.Context | 46 context.Context |
| 37 | 47 |
| 48 // host is the host name of the Coordinator service to interface with. | |
|
Vadim Sh.
2016/09/27 17:58:35
this comment is stale
dnj
2016/09/27 18:13:42
Done.
| |
| 49 p Parameters | |
| 50 | |
| 38 // project is the project name. This may either be a valid project name or | 51 // project is the project name. This may either be a valid project name or |
| 39 // empty. Subcommands that support "unified" project-in-path paths shoul d use | 52 // empty. Subcommands that support "unified" project-in-path paths shoul d use |
| 40 // splitPath to get the project form the path. Those that don't should a ssert | 53 // splitPath to get the project form the path. Those that don't should a ssert |
| 41 // that this is non-empty. | 54 // that this is non-empty. |
| 42 » project config.ProjectName | 55 » project config.ProjectName |
| 43 » authFlags authcli.Flags | 56 » authFlags authcli.Flags |
| 44 » coordinator string | 57 » insecure bool |
| 45 » insecure bool | 58 » timeout clockflag.Duration |
| 46 » timeout clockflag.Duration | |
| 47 | 59 |
| 48 coord *coordinator.Client | 60 coord *coordinator.Client |
| 49 } | 61 } |
| 50 | 62 |
| 51 func (a *application) addToFlagSet(ctx context.Context, fs *flag.FlagSet) { | 63 func (a *application) addToFlagSet(ctx context.Context, fs *flag.FlagSet) { |
| 52 » fs.StringVar(&a.coordinator, "host", "", | 64 » fs.StringVar(&a.p.Host, "host", a.p.Host, |
| 53 "The LogDog Coordinator [host][:port].") | 65 "The LogDog Coordinator [host][:port].") |
| 54 fs.BoolVar(&a.insecure, "insecure", false, | 66 fs.BoolVar(&a.insecure, "insecure", false, |
| 55 "Use insecure transport for RPC.") | 67 "Use insecure transport for RPC.") |
| 56 fs.Var(&a.project, "project", | 68 fs.Var(&a.project, "project", |
| 57 "The log stream's project.") | 69 "The log stream's project.") |
| 58 | 70 |
| 59 fs.Var(&a.timeout, "timeout", | 71 fs.Var(&a.timeout, "timeout", |
| 60 "If >0, a duration string for the maximum amount of time to wait for a log entry "+ | 72 "If >0, a duration string for the maximum amount of time to wait for a log entry "+ |
| 61 "before exiting with a 2. "+clockflag.DurationHelp) | 73 "before exiting with a 2. "+clockflag.DurationHelp) |
| 62 } | 74 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 87 return project, p, true, nil | 99 return project, p, true, nil |
| 88 } | 100 } |
| 89 | 101 |
| 90 func (a *application) timeoutCtx(c context.Context) (context.Context, context.Ca ncelFunc) { | 102 func (a *application) timeoutCtx(c context.Context) (context.Context, context.Ca ncelFunc) { |
| 91 if a.timeout <= 0 { | 103 if a.timeout <= 0 { |
| 92 return context.WithCancel(c) | 104 return context.WithCancel(c) |
| 93 } | 105 } |
| 94 return context.WithTimeout(c, time.Duration(a.timeout)) | 106 return context.WithTimeout(c, time.Duration(a.timeout)) |
| 95 } | 107 } |
| 96 | 108 |
| 97 func mainImpl() int { | 109 // Main is the entry point for the CLI application. |
| 98 » ctx := context.Background() | 110 func Main(ctx context.Context, params Parameters) int { |
| 99 ctx = gologger.StdConfig.Use(ctx) | 111 ctx = gologger.StdConfig.Use(ctx) |
| 100 | 112 |
| 101 authOptions := auth.Options{ | 113 authOptions := auth.Options{ |
| 102 Scopes: coordinator.Scopes, | 114 Scopes: coordinator.Scopes, |
| 103 } | 115 } |
| 104 | 116 |
| 105 a := application{ | 117 a := application{ |
| 106 Application: cli.Application{ | 118 Application: cli.Application{ |
| 107 Name: "LogDog cat", | 119 Name: "LogDog cat", |
| 108 Title: "LogDog log data access CLI", | 120 Title: "LogDog log data access CLI", |
| 109 Context: func(context.Context) context.Context { return ctx }, | 121 Context: func(context.Context) context.Context { return ctx }, |
| 110 | 122 |
| 111 Commands: []*subcommands.Command{ | 123 Commands: []*subcommands.Command{ |
| 112 subcommands.CmdHelp, | 124 subcommands.CmdHelp, |
| 113 newCatCommand(), | 125 newCatCommand(), |
| 114 newQueryCommand(), | 126 newQueryCommand(), |
| 115 newListCommand(), | 127 newListCommand(), |
| 116 newLatestCommand(), | 128 newLatestCommand(), |
| 117 authcli.SubcommandLogin(authOptions, "auth-login "), | 129 authcli.SubcommandLogin(authOptions, "auth-login "), |
| 118 authcli.SubcommandLogout(authOptions, "auth-logo ut"), | 130 authcli.SubcommandLogout(authOptions, "auth-logo ut"), |
| 119 authcli.SubcommandInfo(authOptions, "auth-info") , | 131 authcli.SubcommandInfo(authOptions, "auth-info") , |
| 120 }, | 132 }, |
| 121 }, | 133 }, |
| 134 p: params, | |
| 122 } | 135 } |
| 123 loggingConfig := log.Config{ | 136 loggingConfig := log.Config{ |
| 124 Level: log.Level(log.Info), | 137 Level: log.Level(log.Info), |
| 125 } | 138 } |
| 126 | 139 |
| 127 flags := &flag.FlagSet{} | 140 flags := &flag.FlagSet{} |
| 128 a.addToFlagSet(ctx, flags) | 141 a.addToFlagSet(ctx, flags) |
| 129 loggingConfig.AddFlags(flags) | 142 loggingConfig.AddFlags(flags) |
| 130 a.authFlags.Register(flags, authOptions) | 143 a.authFlags.Register(flags, authOptions) |
| 131 | 144 |
| 132 // Parse flags. | 145 // Parse flags. |
| 133 » if err := flags.Parse(os.Args[1:]); err != nil { | 146 » if err := flags.Parse(params.Args); err != nil { |
| 134 log.Errorf(log.SetError(ctx, err), "Failed to parse command-line .") | 147 log.Errorf(log.SetError(ctx, err), "Failed to parse command-line .") |
| 135 return 1 | 148 return 1 |
| 136 } | 149 } |
| 137 | 150 |
| 138 // Install our log formatter. | 151 // Install our log formatter. |
| 139 ctx = loggingConfig.Set(ctx) | 152 ctx = loggingConfig.Set(ctx) |
| 140 | 153 |
| 141 » if a.coordinator == "" { | 154 » if a.p.Host == "" { |
| 142 log.Errorf(ctx, "Missing coordinator host (-host).") | 155 log.Errorf(ctx, "Missing coordinator host (-host).") |
| 143 return 1 | 156 return 1 |
| 144 } | 157 } |
| 145 | 158 |
| 146 // Signal handler will cancel our context when interrupted. | 159 // Signal handler will cancel our context when interrupted. |
| 147 ctx, cancelFunc := context.WithCancel(ctx) | 160 ctx, cancelFunc := context.WithCancel(ctx) |
| 148 signalC := make(chan os.Signal) | 161 signalC := make(chan os.Signal) |
| 149 signal.Notify(signalC, os.Interrupt, os.Kill) | 162 signal.Notify(signalC, os.Interrupt, os.Kill) |
| 150 go func() { | 163 go func() { |
| 151 triggered := false | 164 triggered := false |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 174 } | 187 } |
| 175 httpClient, err := auth.NewAuthenticator(ctx, auth.OptionalLogin, authOp ts).Client() | 188 httpClient, err := auth.NewAuthenticator(ctx, auth.OptionalLogin, authOp ts).Client() |
| 176 if err != nil { | 189 if err != nil { |
| 177 log.Errorf(log.SetError(ctx, err), "Failed to create authenticat ed client.") | 190 log.Errorf(log.SetError(ctx, err), "Failed to create authenticat ed client.") |
| 178 return 1 | 191 return 1 |
| 179 } | 192 } |
| 180 | 193 |
| 181 // Get our Coordinator client instance. | 194 // Get our Coordinator client instance. |
| 182 prpcClient := &prpc.Client{ | 195 prpcClient := &prpc.Client{ |
| 183 C: httpClient, | 196 C: httpClient, |
| 184 » » Host: a.coordinator, | 197 » » Host: a.p.Host, |
| 185 Options: prpc.DefaultOptions(), | 198 Options: prpc.DefaultOptions(), |
| 186 } | 199 } |
| 187 prpcClient.Options.Insecure = a.insecure | 200 prpcClient.Options.Insecure = a.insecure |
| 188 | 201 |
| 189 a.coord = coordinator.NewClient(prpcClient) | 202 a.coord = coordinator.NewClient(prpcClient) |
| 190 a.Context = ctx | 203 a.Context = ctx |
| 191 return subcommands.Run(&a, flags.Args()) | 204 return subcommands.Run(&a, flags.Args()) |
| 192 } | 205 } |
| 193 | |
| 194 func main() { | |
| 195 os.Exit(mainImpl()) | |
| 196 } | |
| OLD | NEW |