Skip to content

Commit

Permalink
Feature/improve gcp experience (#20)
Browse files Browse the repository at this point in the history
* Initial GCP native auth (no gcloud needed)

* Add ability to force re-authentication;

* Added debug command for development.
  • Loading branch information
aurc authored Aug 16, 2022
1 parent ed29d32 commit d71826a
Show file tree
Hide file tree
Showing 18 changed files with 636 additions and 36 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ Note that you can pipe to anything that produces an output to the `stdin`.
### `gcp-stream` Command
l`oGGo natively supports GCP Logging but in order to use this feature, there are a few caveats:
- You have [gcloud command line SDK](https://cloud.google.com/sdk/docs/install) installed locally.
- Your account has the required permissions to access the logging resources.
- Your personal account has the required permissions to access the logging resources.
Note: `gcp-stream` **does not** support piped commands. If you want to use piped
Expand All @@ -191,14 +190,15 @@ Usage:

Flags:
-f, --filter string Standard GCP filters
--force-auth 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")
-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
Expand Down
47 changes: 47 additions & 0 deletions cmd/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Copyright © 2022 Aurelio Calegari, et al.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package cmd

import (
"github.com/aurc/loggo/internal/loggo"
"github.com/aurc/loggo/internal/reader"
"github.com/spf13/cobra"
)

// streamCmd represents the stream command
var debugCmd = &cobra.Command{
Use: "debug",
Short: "Continuously stream l'oggo log",
Long: `This command aims to assist troubleshoot loggos issue and would be rarely utilised by loggo's users':
loggo debug`,
Run: func(cmd *cobra.Command, args []string) {
reader := reader.MakeReader(loggo.LatestLog, nil)
app := loggo.NewLoggoApp(reader, "")
app.Run()
},
}

func init() {
rootCmd.AddCommand(debugCmd)
}
29 changes: 20 additions & 9 deletions cmd/gcpstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ package cmd

import (
"context"
"log"
"strconv"
"time"

"github.com/aurc/loggo/internal/util"

"github.com/aurc/loggo/internal/gcp"

"github.com/aurc/loggo/internal/loggo"
"github.com/aurc/loggo/internal/reader"
"github.com/spf13/cobra"
Expand All @@ -40,9 +43,10 @@ var gcpStreamCmd = &cobra.Command{
Long: `Continuously stream Google Cloud Platform log entries
from a given selected project and GCP logging filters:
loggo gcp-stream --project myGCPProject123 --from 1m \
--filter 'resource.labels.namespace_name="awesome-sit" AND resource.labels.container_name="some"' \
--template
loggo gcp-stream \
--project myGCPProject123 \
--from 1m \
--filter 'resource.labels.namespace_name="awesome-sit" AND resource.labels.container_name="some"'
`,
Run: func(cmd *cobra.Command, args []string) {
projectName := cmd.Flag("project").Value.String()
Expand All @@ -53,6 +57,10 @@ 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()
auth, _ := strconv.ParseBool(cmd.Flag("force-auth").Value.String())
if auth {
gcp.Delete()
}
if len(saveParams) > 0 {
if err := reader.Save(saveParams,
&reader.SavedParams{
Expand All @@ -61,12 +69,12 @@ from a given selected project and GCP logging filters:
Project: projectName,
Template: templateFile,
}); err != nil {
log.Fatal(err)
util.Log().Fatal(err)
}
} else if lp {
l, err := reader.List()
if err != nil {
log.Fatal(err)
util.Log().Fatal(err)
}
for _, v := range l {
v.Print()
Expand All @@ -75,7 +83,7 @@ from a given selected project and GCP logging filters:
if len(loadParams) > 0 {
p, err := reader.Load(loadParams)
if err != nil {
log.Fatal(err)
util.Log().Fatal(err)
}
if len(templateFile) == 0 && len(p.Template) > 0 {
templateFile = p.Template
Expand All @@ -91,11 +99,11 @@ from a given selected project and GCP logging filters:
}
}
if len(projectName) == 0 {
log.Fatal("--project flag is required.")
util.Log().Fatal("--project flag is required.")
}
err := reader.CheckAuth(context.Background(), projectName)
if err != nil {
log.Fatal("Unable to obtain GCP credentials. ", err)
util.Log().Fatal("Unable to obtain GCP credentials. ", err)
}
time.Sleep(time.Second)
reader := reader.MakeGCPReader(projectName, filter, reader.ParseFrom(from), nil)
Expand Down Expand Up @@ -138,4 +146,7 @@ provided, it overrides the loaded parameter with the one explicitly provided.`)
BoolP("params-list", "", false,
"List saved gcp connection/filtering parameters for convenient reuse.")
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.")
}
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ THE SOFTWARE.
package cmd

import (
"github.com/aurc/loggo/internal/loggo"
"os"

"github.com/aurc/loggo/internal/loggo"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -59,5 +59,5 @@ func init() {

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
//rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
4 changes: 2 additions & 2 deletions cmd/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ package cmd
import (
"github.com/aurc/loggo/internal/config"
"github.com/aurc/loggo/internal/loggo"
"github.com/aurc/loggo/internal/util"
"github.com/spf13/cobra"
"log"
)

// templateCmd represents the template command
Expand Down Expand Up @@ -61,7 +61,7 @@ To start from an example template:
cfg, err = config.MakeConfig(templateFile)
}
if err != nil {
log.Fatalln("Unable to start app: ", err)
util.Log().Fatal("Unable to start app: ", err)
}
app := loggo.NewAppWithConfig(cfg)
view := loggo.NewTemplateView(app, true, nil, nil)
Expand Down
42 changes: 42 additions & 0 deletions internal/char/canvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ THE SOFTWARE.
package char

import (
"bufio"
"bytes"
"fmt"
"strings"
)

Expand Down Expand Up @@ -131,6 +134,45 @@ func (c *Canvas) PrintCanvas() [][]rune {
return bc
}

func (c *Canvas) PrintCanvasAsHtml() string {
str := c.PrintCanvasAsString()
buf := bytes.NewBufferString(str)
reader := bufio.NewReader(buf)
builder := strings.Builder{}
convMap := map[rune]string{
'▓': "▓",
'░': "░",
'╬': "╬",
'╦': "╦",
'╩': "╩",
'╠': "╠",
'╣': "╣",
'╔': "╔",
'╗': "╗",
'╚': "╚",
'╝': "╝",
}
paintChar := '▓'
shade := '░'
for {
str, err := reader.ReadString('\n')
if err == nil {
for _, char := range str {
switch char {
case paintChar, shade:
builder.WriteString(fmt.Sprintf(`<span class="fgCol">%s</span>`, convMap[char]))
default:
builder.WriteString(fmt.Sprintf(`<span class="bgCol">%s</span>`, convMap[char]))
}
}
builder.WriteString("<br>\n")
} else {
break
}
}
return builder.String()
}

func (c *Canvas) PrintCanvasAsString() string {
return c.toString(c.PrintCanvas())
}
Expand Down
9 changes: 8 additions & 1 deletion internal/char/canvas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ package char

import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"

"github.com/stretchr/testify/assert"
)

func TestCanvas_BlankCanvas(t *testing.T) {
Expand Down Expand Up @@ -152,3 +153,9 @@ func TestCanvas_BlankCanvasAsString(t *testing.T) {
})
}
}

func TestCanvas_PrintCanvasAsHtml(t *testing.T) {
c := NewCanvas().WithWord(LoggoLogo...)
str := c.PrintCanvasAsHtml()
fmt.Println(str)
}
69 changes: 69 additions & 0 deletions internal/gcp/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright © 2022 Aurelio Calegari, et al.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package gcp

import (
"encoding/json"
"os"
"path"
)

type Auth struct {
ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RefreshToken string `json:"refresh_token"`
Type string `json:"type"`
}

func AuthDir() string {
hd, _ := os.UserHomeDir()
dir := path.Join(hd, ".loggo", "auth")
return dir
}

func AuthFile() string {
return path.Join(AuthDir(), "gcp.json")
}

func Delete() {
_ = os.Remove(AuthFile())
}

func (a *Auth) Save() error {
if err := os.MkdirAll(AuthDir(), os.ModePerm); err != nil {
return err
}
b, err := json.MarshalIndent(a, "", " ")
if err != nil {
return err
}

file, err := os.Create(AuthFile())
if err != nil {
return err
}
defer file.Close()

_, err = file.Write(b)
return err
}
Loading

0 comments on commit d71826a

Please sign in to comment.