From 9d70eb163678ff8b8444580ef01a66f1f7c82362 Mon Sep 17 00:00:00 2001 From: aurc <54873456+aurc@users.noreply.github.com> Date: Wed, 17 Aug 2022 16:53:03 +1000 Subject: [PATCH] A few UI tweaks and ability to use either gcloud CLI installation or loggo native connector for GCP auth. --- README.md | 13 ++++++++++--- cmd/gcpstream.go | 12 ++++++++++-- internal/gcp/auth.go | 26 ++++++++++++++++++++------ internal/loggo/log_view_nav_menu.go | 9 +++++---- internal/reader/gcp_reader.go | 16 +++++++++++----- 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index c13df69..720fca9 100644 --- a/README.md +++ b/README.md @@ -189,23 +189,30 @@ Usage: loggo gcp-stream [flags] Flags: + -p, --project string GCP Project ID (required) + + ------------------- Optional Below ------------------ + -f, --filter string Standard GCP filters - --force-auth Force re-authentication even if you may have a valid authentication file. + --force-auth Only effective if combined with gcloud flag. Force re-authentication even + if you may have a valid authentication file. -d, --from string Start streaming from: Relative: Use format "1s", "1m", "1h" or "1d", where: digit followed by s, m, h, d as second, minute, hour, day. Fixed: Use date format as "yyyy-MM-ddH24:mm:ss", e.g. 2022-07-30T15:00:00 Now: Use "tail" to start from now (default "tail") + --gcloud-auth Use the existing GCloud CLI infrastructure installed on your system for GCP + authentication. You must have gcloud CLI installed and configured. If this + flag is not passed, it uses l'oggo native connector. -h, --help help for gcp-stream --params-list List saved gcp connection/filtering parameters for convenient reuse. - --params-load string Load the parameters for reuse. If any additional parameters are + --params-load string Load the parameters for reuse. If any additional parameters are provided, it overrides the loaded parameter with the one explicitly provided. --params-save string Save the following parameters (if provided) for reuse: Project: The GCP Project ID Template: The rendering template to be applied. From: When to start streaming from. Filter: The GCP specific filter parameters. - -p, --project string GCP Project ID (required) -t, --template string Rendering Template ```` diff --git a/cmd/gcpstream.go b/cmd/gcpstream.go index e509cdd..21f78c0 100644 --- a/cmd/gcpstream.go +++ b/cmd/gcpstream.go @@ -49,6 +49,7 @@ from a given selected project and GCP logging filters: --filter 'resource.labels.namespace_name="awesome-sit" AND resource.labels.container_name="some"' `, Run: func(cmd *cobra.Command, args []string) { + util.Log().WithField("code", cmd.Flags()).Info("GCP Stream Params") projectName := cmd.Flag("project").Value.String() from := cmd.Flag("from").Value.String() filter := cmd.Flag("filter").Value.String() @@ -57,8 +58,9 @@ from a given selected project and GCP logging filters: listParams := cmd.Flag("params-list").Value.String() lp, _ := strconv.ParseBool(listParams) loadParams := cmd.Flag("params-load").Value.String() + gcp.IsGCloud, _ = strconv.ParseBool(cmd.Flag("gcloud-auth").Value.String()) auth, _ := strconv.ParseBool(cmd.Flag("force-auth").Value.String()) - if auth { + if auth && gcp.IsGCloud { gcp.Delete() } if len(saveParams) > 0 { @@ -148,5 +150,11 @@ provided, it overrides the loaded parameter with the one explicitly provided.`) gcpStreamCmd.MarkFlagsMutuallyExclusive("params-save", "params-load", "params-list") gcpStreamCmd.Flags(). BoolP("force-auth", "", false, - "Force re-authentication even if you may have a valid authentication file.") + `Only effective if combined with gcloud flag. Force re-authentication even +if you may have a valid authentication file.`) + gcpStreamCmd.Flags(). + BoolP("gcloud-auth", "", false, + `Use the existing GCloud CLI infrastructure installed on your system for GCP +authentication. You must have gcloud CLI installed and configured. If this +flag is not passed, it use l'oggo native connector.`) } diff --git a/internal/gcp/auth.go b/internal/gcp/auth.go index 9e0dcc6..6ae0a28 100644 --- a/internal/gcp/auth.go +++ b/internal/gcp/auth.go @@ -23,11 +23,17 @@ THE SOFTWARE. package gcp import ( + "context" "encoding/json" "os" "path" + + logging "cloud.google.com/go/logging/apiv2" + "google.golang.org/api/option" ) +var IsGCloud = false + type Auth struct { ClientId string `json:"client_id"` ClientSecret string `json:"client_secret"` @@ -35,22 +41,30 @@ type Auth struct { Type string `json:"type"` } -func AuthDir() string { +func LoggingClient(ctx context.Context) (*logging.Client, error) { + if !IsGCloud { + return logging.NewClient(ctx, option.WithCredentialsFile(authFile())) + } else { + return logging.NewClient(ctx) + } +} + +func authDir() string { hd, _ := os.UserHomeDir() dir := path.Join(hd, ".loggo", "auth") return dir } -func AuthFile() string { - return path.Join(AuthDir(), "gcp.json") +func authFile() string { + return path.Join(authDir(), "gcp.json") } func Delete() { - _ = os.Remove(AuthFile()) + _ = os.Remove(authFile()) } func (a *Auth) Save() error { - if err := os.MkdirAll(AuthDir(), os.ModePerm); err != nil { + if err := os.MkdirAll(authDir(), os.ModePerm); err != nil { return err } b, err := json.MarshalIndent(a, "", " ") @@ -58,7 +72,7 @@ func (a *Auth) Save() error { return err } - file, err := os.Create(AuthFile()) + file, err := os.Create(authFile()) if err != nil { return err } diff --git a/internal/loggo/log_view_nav_menu.go b/internal/loggo/log_view_nav_menu.go index 4c16872..91dae77 100644 --- a/internal/loggo/log_view_nav_menu.go +++ b/internal/loggo/log_view_nav_menu.go @@ -34,7 +34,7 @@ import ( func (l *LogView) populateMenu() { l.navMenu = tview.NewFlex().SetDirection(tview.FlexRow) l.navMenu. - SetBackgroundColor(color.ColorBackgroundField).SetBorderPadding(0, 0, 1, 0) + SetBackgroundColor(color.ColorBackgroundField).SetBorderPadding(0, 0, 0, 0) sepForeground := tview.Styles.ContrastBackgroundColor sepStyle := tcell.StyleDefault.Background(tcell.ColorBlack).Foreground(sepForeground) l.navMenu. @@ -125,7 +125,8 @@ func (l *LogView) populateMenu() { SetDynamicColors(true). SetText(`[yellow::b] ^c [-::u]["1"]Quit[""]`), func() { l.app.Stop() - }), 0, 1, false). + }), 1, 1, false). + AddItem(NewHorizontalSeparator(sepStyle, LineHThick, "", sepForeground), 1, 2, false). AddItem(tview.NewBox(), 0, 1, false). AddItem(l.linesView, 1, 1, false) @@ -210,8 +211,8 @@ func (l *LogView) updateLineView() { l.globalCount)) } if l.isFollowing { - l.followingView.SetText(`[yellow::b] ^Space [-::u]["1"]Stream[::-] [green::bi]ON[-::-][""]`) + l.followingView.SetText(`[yellow::b] ^Space [-::u]["1"]Auto-Scroll[::-] [green::bi]ON[-::-][""]`) } else { - l.followingView.SetText(`[yellow::b] ^Space [-::u]["1"]Stream[::-] [red::bi]OFF[-::-][""]`) + l.followingView.SetText(`[yellow::b] ^Space [-::u]["1"]Auto-Scroll[::-] [red::bi]OFF[-::-][""]`) } } diff --git a/internal/reader/gcp_reader.go b/internal/reader/gcp_reader.go index 6a9fc3b..1c3bf66 100644 --- a/internal/reader/gcp_reader.go +++ b/internal/reader/gcp_reader.go @@ -27,6 +27,7 @@ import ( "encoding/json" "fmt" "io" + "os/exec" "regexp" "strconv" "strings" @@ -34,8 +35,6 @@ import ( "github.com/aurc/loggo/internal/util" - "google.golang.org/api/option" - "github.com/aurc/loggo/internal/gcp" logging "cloud.google.com/go/logging/apiv2" @@ -87,7 +86,7 @@ func (s *gcpStream) StreamInto() (err error) { }() ctx := context.Background() var c *logging.Client - c, err = logging.NewClient(ctx, option.WithCredentialsFile(gcp.AuthFile())) + c, err = gcp.LoggingClient(ctx) if err != nil { return err } @@ -207,7 +206,7 @@ func (s *gcpStream) Close() { } func CheckAuth(ctx context.Context, projectID string) error { - c, err := logging.NewClient(ctx, option.WithCredentialsFile(gcp.AuthFile())) + c, err := gcp.LoggingClient(ctx) if err == nil { it := c.ListLogs(ctx, &loggingpb.ListLogsRequest{ ResourceNames: []string{"projects/" + projectID}, @@ -221,7 +220,14 @@ func CheckAuth(ctx context.Context, projectID string) error { SetText("Authenticating with gcloud... \nRedirecting to your browser.") go func() { defer app.Stop() - gcp.OAuth() + if !gcp.IsGCloud { + gcp.OAuth() + } else { + cmd := exec.Command("gcloud", "auth", "application-default", "login") + if err := cmd.Run(); err != nil { + util.Log().Fatal(err) + } + } }() if err := app.SetRoot(modal, false).EnableMouse(true).Run(); err != nil {