| Index: logdog/client/butlerlib/bootstrap/bootstrap.go
|
| diff --git a/logdog/client/butlerlib/bootstrap/bootstrap.go b/logdog/client/butlerlib/bootstrap/bootstrap.go
|
| index 34ee46e1942f4ecee15422112a14ffb087b95c8d..c9e9bc8370027a2018f15ffc7b35c65a8dde647a 100644
|
| --- a/logdog/client/butlerlib/bootstrap/bootstrap.go
|
| +++ b/logdog/client/butlerlib/bootstrap/bootstrap.go
|
| @@ -5,13 +5,14 @@
|
| package bootstrap
|
|
|
| import (
|
| - "errors"
|
| "fmt"
|
|
|
| "github.com/luci/luci-go/client/environ"
|
| "github.com/luci/luci-go/common/config"
|
| + "github.com/luci/luci-go/common/errors"
|
| "github.com/luci/luci-go/logdog/client/butlerlib/streamclient"
|
| "github.com/luci/luci-go/logdog/common/types"
|
| + "github.com/luci/luci-go/logdog/common/viewer"
|
| )
|
|
|
| // ErrNotBootstrapped is returned by Get when the current process is not
|
| @@ -62,19 +63,58 @@ func getFromEnv(env environ.Environment, reg *streamclient.Registry) (*Bootstrap
|
|
|
| // If we have a stream server attached; instantiate a stream Client.
|
| if p, ok := env[EnvStreamServerPath]; ok {
|
| - c, err := reg.NewClient(p)
|
| - if err != nil {
|
| + if err := bs.initializeClient(p, reg); err != nil {
|
| return nil, fmt.Errorf("bootstrap: failed to create stream client [%s]: %s", p, err)
|
| }
|
| - bs.Client = c
|
| }
|
|
|
| return bs, nil
|
| }
|
|
|
| +func (bs *Bootstrap) initializeClient(v string, reg *streamclient.Registry) error {
|
| + c, err := reg.NewClient(v)
|
| + if err != nil {
|
| + return errors.Annotate(err).Reason("bootstrap: failed to create stream client [%(config)s]").D("config", v).Err()
|
| + }
|
| + bs.Client = c
|
| + return nil
|
| +}
|
| +
|
| // Get loads a Bootstrap instance from the environment. It will return an error
|
| // if the bootstrap data is invalid, and will return ErrNotBootstrapped if the
|
| // current process is not bootstrapped.
|
| func Get() (*Bootstrap, error) {
|
| - return getFromEnv(environ.Get(), streamclient.DefaultRegistry)
|
| + return getFromEnv(environ.Get(), streamclient.GetDefaultRegistry())
|
| +}
|
| +
|
| +// GetViewerURL returns a log stream viewer URL to the aggregate set of supplied
|
| +// stream paths.
|
| +//
|
| +// If both the Project and CoordinatorHost values are not populated, an error
|
| +// will be returned.
|
| +func (bs *Bootstrap) GetViewerURL(paths ...types.StreamPath) (string, error) {
|
| + if bs.Project == "" {
|
| + return "", errors.New("no project is configured")
|
| + }
|
| + if bs.CoordinatorHost == "" {
|
| + return "", errors.New("no coordinator host is configured")
|
| + }
|
| + return viewer.GetURL(bs.CoordinatorHost, bs.Project, paths...), nil
|
| +}
|
| +
|
| +// GetViewerURLForStreams returns a log stream viewer URL to the aggregate set
|
| +// of supplied streams.
|
| +//
|
| +// If the any of the Prefix, Project, or CoordinatorHost values is not
|
| +// populated, an error will be returned.
|
| +func (bs *Bootstrap) GetViewerURLForStreams(streams ...streamclient.Stream) (string, error) {
|
| + if bs.Prefix == "" {
|
| + return "", errors.New("no prefix is configured")
|
| + }
|
| +
|
| + paths := make([]types.StreamPath, len(streams))
|
| + for i, s := range streams {
|
| + paths[i] = bs.Prefix.Join(types.StreamName(s.Properties().Name))
|
| + }
|
| + return bs.GetViewerURL(paths...)
|
| }
|
|
|