re-write all the things
This commit is contained in:
parent
313ea55f57
commit
1f05d1579c
@ -25,7 +25,7 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"shiny-pancake/database"
|
"shiny-pancake/internal/model"
|
||||||
|
|
||||||
"os"
|
"os"
|
||||||
"shiny-pancake/logger"
|
"shiny-pancake/logger"
|
||||||
@ -90,7 +90,7 @@ func configWriter(f *tview.Form){
|
|||||||
var fp string
|
var fp string
|
||||||
var hostFile string
|
var hostFile string
|
||||||
var cfg []byte
|
var cfg []byte
|
||||||
var c database.HostDetails
|
var c model.HostDetails
|
||||||
var hd string
|
var hd string
|
||||||
hd = viper.GetString("hostsDirectory")
|
hd = viper.GetString("hostsDirectory")
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ func configWriter(f *tview.Form){
|
|||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Create(fp)
|
file, err := os.Create(fp)
|
||||||
c = database.HostDetails{ip[3], hostFile, ip[1], ip[2]}
|
c = model.HostDetails{ip[3], hostFile, ip[1], ip[2]}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("unable to create file: " + fp)
|
log.Fatal("unable to create file: " + fp)
|
||||||
}
|
}
|
||||||
|
|||||||
14
cmd/load.go
14
cmd/load.go
@ -26,8 +26,9 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"shiny-pancake/database"
|
"shiny-pancake/internal/database"
|
||||||
"shiny-pancake/internal/gui"
|
"shiny-pancake/internal/gui"
|
||||||
|
"shiny-pancake/internal/model"
|
||||||
"shiny-pancake/logger"
|
"shiny-pancake/logger"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -83,9 +84,10 @@ to quickly create a Cobra application.`,
|
|||||||
// Print out the final choice.
|
// Print out the final choice.
|
||||||
if fn = <-result; len(fn) !=0 {
|
if fn = <-result; len(fn) !=0 {
|
||||||
var hostDir string
|
var hostDir string
|
||||||
|
var db *database.Database
|
||||||
hostDir = viper.GetString("hostsDirectory")
|
hostDir = viper.GetString("hostsDirectory")
|
||||||
file, _ := ioutil.ReadFile(hostDir + "/"+ fn)
|
file, _ := ioutil.ReadFile(hostDir + "/"+ fn)
|
||||||
data := database.HostDetails{}
|
data := model.HostDetails{}
|
||||||
err := json.Unmarshal(file, &data)
|
err := json.Unmarshal(file, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var l logger.Log
|
var l logger.Log
|
||||||
@ -97,7 +99,13 @@ to quickly create a Cobra application.`,
|
|||||||
var l logger.Log
|
var l logger.Log
|
||||||
l = logger.Log{"info", logrus.Fields{"loaded": fn }, "config loading to ui"}
|
l = logger.Log{"info", logrus.Fields{"loaded": fn }, "config loading to ui"}
|
||||||
logger.Lgr(&l)
|
logger.Lgr(&l)
|
||||||
gui.Gui(data)
|
db = database.New(&data)
|
||||||
|
|
||||||
|
// Initialise the Gui / Tui
|
||||||
|
gui := gui.New(db)
|
||||||
|
if err := gui.Start(); err != nil {
|
||||||
|
log.Fatalf("main: Cannot start tui: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@ -28,6 +28,7 @@ var (
|
|||||||
hostsDirectory = "hosts"
|
hostsDirectory = "hosts"
|
||||||
logsDirectory = "logs"
|
logsDirectory = "logs"
|
||||||
configDirectory = "config"
|
configDirectory = "config"
|
||||||
|
queryDirectory = "query"
|
||||||
)
|
)
|
||||||
var cfgFile string
|
var cfgFile string
|
||||||
|
|
||||||
@ -91,6 +92,7 @@ func initConfig() {
|
|||||||
viper.SetDefault("hostsDirectory", home + "/" + configHome + "/" + hostsDirectory)
|
viper.SetDefault("hostsDirectory", home + "/" + configHome + "/" + hostsDirectory)
|
||||||
viper.SetDefault("logsDirectory", home + "/" + configHome + "/" + logsDirectory)
|
viper.SetDefault("logsDirectory", home + "/" + configHome + "/" + logsDirectory)
|
||||||
viper.SetDefault("configDirectory", home + "/" +configHome + "/" + configDirectory)
|
viper.SetDefault("configDirectory", home + "/" +configHome + "/" + configDirectory)
|
||||||
|
viper.SetDefault("queryDirectory", home + "/" +configHome + "/" + queryDirectory)
|
||||||
viper.SetDefault("logLevel", "debug")
|
viper.SetDefault("logLevel", "debug")
|
||||||
viper.SetDefault("logfile", "log")
|
viper.SetDefault("logfile", "log")
|
||||||
viper.AutomaticEnv() // read in environment variables that match
|
viper.AutomaticEnv() // read in environment variables that match
|
||||||
@ -118,6 +120,7 @@ func directoryInit() {
|
|||||||
logsDirectory,
|
logsDirectory,
|
||||||
hostsDirectory,
|
hostsDirectory,
|
||||||
configDirectory,
|
configDirectory,
|
||||||
|
queryDirectory,
|
||||||
}
|
}
|
||||||
for _, dr := range s {
|
for _, dr := range s {
|
||||||
if _, err := os.Stat(cfgDir + "/" + dr); os.IsNotExist(err) {
|
if _, err := os.Stat(cfgDir + "/" + dr); os.IsNotExist(err) {
|
||||||
|
|||||||
@ -1,68 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
)
|
|
||||||
|
|
||||||
//func DbConn(c HostDetails) (*sql.DB, error) {
|
|
||||||
// var h string
|
|
||||||
// var u string
|
|
||||||
// var pw string
|
|
||||||
// var dbn string
|
|
||||||
// var psqlInfo string
|
|
||||||
// h = c.Hostname
|
|
||||||
// u = c.Username
|
|
||||||
// pw = c.Secret
|
|
||||||
// dbn = c.DatabaseName
|
|
||||||
//
|
|
||||||
// logger.Logger("[LOG] connection details: host = " + h + " username = " + u)
|
|
||||||
//
|
|
||||||
// found, testUserName := data.ViperPgmConfig("test_user", "r")
|
|
||||||
// if found == true {
|
|
||||||
// logger.Logger("[LOG] found test user in .pgm.yaml")
|
|
||||||
// }
|
|
||||||
// psqlInfo = fmt.Sprintf("host=%s port=%d user=%s "+
|
|
||||||
// "password=%s dbname=%s sslmode=disable",
|
|
||||||
// h, 5432, u, pw, dbn)
|
|
||||||
// db, err := sql.Open("postgres", psqlInfo)
|
|
||||||
// if err != nil {
|
|
||||||
// var db *sql.DB
|
|
||||||
// switch u {
|
|
||||||
// case testUserName:
|
|
||||||
// logger.Logger("[ERROR] go tests expects to connect with the docker compose database." +
|
|
||||||
// "[ERROR] run \"docker-compose up\" and re-run tests")
|
|
||||||
// err := errors.New("unable to ping db" + dbn + "local db is closed, please run docker-compose up")
|
|
||||||
// return db, err
|
|
||||||
// default:
|
|
||||||
// logger.Logger("[ERROR] db error: " + err.Error())
|
|
||||||
// return db, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// logger.Logger("[LOG] pinging db " + dbn)
|
|
||||||
// ctx := context.Background()
|
|
||||||
// err = db.PingContext(ctx)
|
|
||||||
//
|
|
||||||
// if err != nil {
|
|
||||||
// var db *sql.DB
|
|
||||||
// switch u {
|
|
||||||
// case testUserName:
|
|
||||||
// logger.Logger("[ERROR] db error, unable to ping: " + err.Error()+
|
|
||||||
// "\n[ERROR] ensure docker database is running and re-run tests")
|
|
||||||
// fmt.Println("local db is closed, please run docker-compose up")
|
|
||||||
// err1 := errors.New("unable to ping db" + dbn)
|
|
||||||
// return db, err1
|
|
||||||
// default:
|
|
||||||
// logger.Logger("[ERROR] db error: " + err.Error())
|
|
||||||
// return db, err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return db, nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
type HostDetails struct {
|
|
||||||
Secret string `json:"secret"`
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
DatabaseName string `json:"databaseName"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
}
|
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
version: '3.7'
|
||||||
|
|
||||||
|
services:
|
||||||
|
pg-db:
|
||||||
|
image: postgres:11.5
|
||||||
|
container_name: pg-db
|
||||||
|
expose:
|
||||||
|
- "5432"
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=localdb
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_PASSWORD=postgres
|
||||||
|
volumes:
|
||||||
|
- ${PWD}/internal/database/container/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
|
||||||
|
|
||||||
5
go.mod
5
go.mod
@ -4,7 +4,9 @@ go 1.15
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/charmbracelet/bubbletea v0.12.2
|
github.com/charmbracelet/bubbletea v0.12.2
|
||||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591
|
github.com/gdamore/tcell v1.2.0
|
||||||
|
github.com/gdamore/tcell/v2 v2.0.1-0.20201019142633-1057d5591ed1
|
||||||
|
github.com/idlephysicist/cave-logger v1.2.2
|
||||||
github.com/lib/pq v1.8.0
|
github.com/lib/pq v1.8.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/muesli/termenv v0.7.4
|
github.com/muesli/termenv v0.7.4
|
||||||
@ -12,4 +14,5 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
github.com/spf13/cobra v1.1.1
|
github.com/spf13/cobra v1.1.1
|
||||||
github.com/spf13/viper v1.7.1
|
github.com/spf13/viper v1.7.1
|
||||||
|
gitlab.com/tslocum/cview v1.5.1
|
||||||
)
|
)
|
||||||
|
|||||||
31
go.sum
31
go.sum
@ -13,6 +13,7 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
|
|||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
@ -23,6 +24,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
|||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
|
github.com/bvinc/go-sqlite-lite v0.6.1 h1:JU8Rz5YAOZQiU3WEulKF084wfXpytRiqD2IaW2QjPz4=
|
||||||
|
github.com/bvinc/go-sqlite-lite v0.6.1/go.mod h1:2GiE60NUdb0aNhDdY+LXgrqAVDpi2Ijc6dB6ZMp9x6s=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/charmbracelet/bubbletea v0.12.2 h1:y9Yo2Pv8tcm3mAJsWONGsmHhzrbNxJVxpVtemikxE9A=
|
github.com/charmbracelet/bubbletea v0.12.2 h1:y9Yo2Pv8tcm3mAJsWONGsmHhzrbNxJVxpVtemikxE9A=
|
||||||
github.com/charmbracelet/bubbletea v0.12.2/go.mod h1:3gZkYELUOiEUOp0bTInkxguucy/xRbGSOcbMs1geLxg=
|
github.com/charmbracelet/bubbletea v0.12.2/go.mod h1:3gZkYELUOiEUOp0bTInkxguucy/xRbGSOcbMs1geLxg=
|
||||||
@ -43,8 +46,14 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
|
|||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
|
github.com/gdamore/tcell v1.1.2/go.mod h1:h3kq4HO9l2On+V9ed8w8ewqQEmGCSSHOgQ+2h8uzurE=
|
||||||
|
github.com/gdamore/tcell v1.2.0 h1:ikixzsxc8K8o3V2/CEmyoEW8mJZaNYQQ3NP3VIQdUe4=
|
||||||
|
github.com/gdamore/tcell v1.2.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||||
|
github.com/gdamore/tcell/v2 v2.0.0-dev/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591 h1:0WWUDZ1oxq7NxVyGo8M3KI5jbkiwNAdZFFzAdC68up4=
|
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591 h1:0WWUDZ1oxq7NxVyGo8M3KI5jbkiwNAdZFFzAdC68up4=
|
||||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||||
|
github.com/gdamore/tcell/v2 v2.0.1-0.20201019142633-1057d5591ed1 h1:gp9ujdOQmQf1gMvqOYYgxdMS5tRpRGE3HAgRH4Hgzd4=
|
||||||
|
github.com/gdamore/tcell/v2 v2.0.1-0.20201019142633-1057d5591ed1/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
@ -97,6 +106,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
|||||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
|
github.com/idlephysicist/cave-logger v1.2.2 h1:PoGzbYx9rJ1l/hZDA3bDJUW9M++fTMAlAbC7AW8thbI=
|
||||||
|
github.com/idlephysicist/cave-logger v1.2.2/go.mod h1:BZG2qItPt8BnN/+T837nzY57qRihQXcb2YXUZoRYcrU=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
@ -106,11 +117,13 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
|||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
@ -118,6 +131,7 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
|
|||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
@ -154,8 +168,10 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
|||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
github.com/rivo/tview v0.0.0-20190829161255-f8bc69b90341/go.mod h1:+rKjP5+h9HMwWRpAfhIkkQ9KE3m3Nz5rwn7YtUpwgqk=
|
||||||
github.com/rivo/tview v0.0.0-20201018122409-d551c850a743 h1:9BBjVJTRxuYBeCAv9DFH2hSzY0ujLx5sxMg5D3K/Xeg=
|
github.com/rivo/tview v0.0.0-20201018122409-d551c850a743 h1:9BBjVJTRxuYBeCAv9DFH2hSzY0ujLx5sxMg5D3K/Xeg=
|
||||||
github.com/rivo/tview v0.0.0-20201018122409-d551c850a743/go.mod h1:t7mcA3nlK9dxD1DMoz/DQRMWFMkGBUj6rJBM5VNfLFA=
|
github.com/rivo/tview v0.0.0-20201018122409-d551c850a743/go.mod h1:t7mcA3nlK9dxD1DMoz/DQRMWFMkGBUj6rJBM5VNfLFA=
|
||||||
|
github.com/rivo/uniseg v0.0.0-20190513083848-b9f5b9457d44/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
@ -165,6 +181,7 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
|
|||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
@ -184,9 +201,14 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
gitlab.com/tslocum/cbind v0.1.3 h1:FT/fTQ4Yj3eo5021lB3IbkIt8eVtYGhrw/xur+cjvUU=
|
||||||
|
gitlab.com/tslocum/cbind v0.1.3/go.mod h1:RvwYE3auSjBNlCmWeGspzn+jdLUVQ8C2QGC+0nP9ChI=
|
||||||
|
gitlab.com/tslocum/cview v1.5.1 h1:1zHvNJvyhHxAVBf3FsSzzqgB15mrojNEm7VbvLXWcpQ=
|
||||||
|
gitlab.com/tslocum/cview v1.5.1/go.mod h1:BRtUi0zXzVXufhqFm/1GD7GL+iznKh5m9pEGN19SnKA=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
@ -249,24 +271,31 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7 h1:XtNJkfEjb4zR3q20BBBcYUykVOEMgZeIUOpBPfNYgxg=
|
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7 h1:XtNJkfEjb4zR3q20BBBcYUykVOEMgZeIUOpBPfNYgxg=
|
||||||
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck=
|
||||||
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||||
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -311,11 +340,13 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
|
|||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|||||||
21
internal/database/container/init.sql
Normal file
21
internal/database/container/init.sql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
create schema test;
|
||||||
|
create table test.employees (
|
||||||
|
Id SERIAL NOT NULL PRIMARY KEY,
|
||||||
|
Name VARCHAR(50),
|
||||||
|
Location VARCHAR(50)
|
||||||
|
);
|
||||||
|
create table test.company (
|
||||||
|
cid SERIAL NOT NULL PRIMARY KEY,
|
||||||
|
Name VARCHAR(50)
|
||||||
|
);
|
||||||
|
create table test.employer (
|
||||||
|
eid SERIAL NOT NULL PRIMARY KEY,
|
||||||
|
Id INT,
|
||||||
|
cid INT
|
||||||
|
);
|
||||||
|
ALTER TABLE test.employer add constraint emp_fk foreign key(Id) REFERENCES test.employees(id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||||
|
insert into test.employees (name,location) VALUES ('bob','kalamazoo');
|
||||||
|
create role test with login password 'test';
|
||||||
|
insert into test.employees (name,location) VALUES ('cheeks','magoo');
|
||||||
|
update test.employees set location = 'buttsville' where name = 'cheeks';
|
||||||
|
grant all privileges on schema test to test;
|
||||||
77
internal/database/database.go
Normal file
77
internal/database/database.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"shiny-pancake/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
const datetime = `2006-01-02T15:04:05Z`
|
||||||
|
const date = `2006-01-02`
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
conn *sql.DB
|
||||||
|
log *logrus.Logger
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(c *model.HostDetails) *Database {
|
||||||
|
var db Database
|
||||||
|
var h string
|
||||||
|
var u string
|
||||||
|
var pw string
|
||||||
|
var dbn string
|
||||||
|
var psqlInfo string
|
||||||
|
var log *logrus.Logger
|
||||||
|
h = c.Hostname
|
||||||
|
u = c.Username
|
||||||
|
pw = c.Secret
|
||||||
|
dbn = c.DatabaseName
|
||||||
|
|
||||||
|
db.ctx = context.Background()
|
||||||
|
db.log = log
|
||||||
|
psqlInfo = fmt.Sprintf("host=%s port=%d user=%s "+
|
||||||
|
"password=%s dbname=%s sslmode=disable",
|
||||||
|
h, 5432, u, pw, dbn)
|
||||||
|
dbC, err := sql.Open("postgres", psqlInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("database.new: Cannot establish connection to %s: %v", h, err)
|
||||||
|
}
|
||||||
|
db.conn = dbC
|
||||||
|
return &db
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (db *Database) UserSessions() ([]*model.Session, error) {
|
||||||
|
query := `select usename, count(usename) from pg_stat_activity where usename is not null group by usename`
|
||||||
|
|
||||||
|
rows, err := db.conn.Query(query)
|
||||||
|
if err != nil {
|
||||||
|
// handle this error better than this
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sessions := make([]*model.Session, 0)
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
var sessCount model.Session
|
||||||
|
err = rows.Scan(&sessCount.Username, &sessCount.Count)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// handle this error
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sessions = append(sessions, &sessCount)
|
||||||
|
|
||||||
|
}
|
||||||
|
// get any error encountered during iteration
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return sessions, err
|
||||||
|
}
|
||||||
4
internal/database/query.toml
Normal file
4
internal/database/query.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[sessions.Current]
|
||||||
|
columns = 2
|
||||||
|
headers = ["users", "count users"]
|
||||||
|
query = "select usename, count(usename) from pg_stat_activity where usename is not null"
|
||||||
@ -1,367 +1,367 @@
|
|||||||
package gui
|
package gui
|
||||||
|
//
|
||||||
import (
|
//import (
|
||||||
"database/sql"
|
// "database/sql"
|
||||||
"fmt"
|
// "fmt"
|
||||||
"github.com/sirupsen/logrus"
|
// "github.com/sirupsen/logrus"
|
||||||
"reflect"
|
// "reflect"
|
||||||
"shiny-pancake/database"
|
// "shiny-pancake/internal/database"
|
||||||
"shiny-pancake/logger"
|
// "shiny-pancake/logger"
|
||||||
"strconv"
|
// "strconv"
|
||||||
"sync"
|
// "sync"
|
||||||
"time"
|
// "time"
|
||||||
|
//
|
||||||
"github.com/gdamore/tcell/v2"
|
// "github.com/gdamore/tcell/v2"
|
||||||
_ "github.com/lib/pq"
|
// _ "github.com/lib/pq"
|
||||||
"github.com/rivo/tview"
|
// "github.com/rivo/tview"
|
||||||
)
|
//)
|
||||||
|
//
|
||||||
const (
|
//const (
|
||||||
batchSize = 80 // The number of rows loaded per batch.
|
// batchSize = 80 // The number of rows loaded per batch.
|
||||||
finderPage = "*finder*" // The name of the Finder page.
|
// finderPage = "*finder*" // The name of the Finder page.
|
||||||
)
|
//)
|
||||||
|
//
|
||||||
var (
|
//var (
|
||||||
app *tview.Application // The tview application.
|
// app *tview.Application // The tview application.
|
||||||
pages *tview.Pages // The application pages.
|
// panels *tview.Pages // The application panels.
|
||||||
finderFocus tview.Primitive // The primitive in the Finder that last had focus.
|
// finderFocus tview.Primitive // The primitive in the Finder that last had focus.
|
||||||
)
|
//)
|
||||||
|
//
|
||||||
// Main entry point.
|
//// Main entry point.
|
||||||
func data(host database.HostDetails) {
|
//func data(host database.HostDetails) {
|
||||||
var h string
|
// var h string
|
||||||
var u string
|
// var u string
|
||||||
var pw string
|
// var pw string
|
||||||
var dbn string
|
// var dbn string
|
||||||
var psqlInfo string
|
// var psqlInfo string
|
||||||
h = host.Hostname
|
// h = host.Hostname
|
||||||
u = host.Username
|
// u = host.Username
|
||||||
pw = host.Secret
|
// pw = host.Secret
|
||||||
dbn = host.DatabaseName
|
// dbn = host.DatabaseName
|
||||||
// Start the application.
|
// // Start the application.
|
||||||
psqlInfo = fmt.Sprintf("host=%s port=%d user=%s "+
|
// psqlInfo = fmt.Sprintf("host=%s port=%d user=%s "+
|
||||||
"password=%s dbname=%s sslmode=disable",
|
// "password=%s dbname=%s sslmode=disable",
|
||||||
h, 5432, u, pw, dbn)
|
// h, 5432, u, pw, dbn)
|
||||||
app = tview.NewApplication()
|
// app = tview.NewApplication()
|
||||||
finder(psqlInfo)
|
// finder(psqlInfo)
|
||||||
if err := app.Run(); err != nil {
|
// if err := app.Run(); err != nil {
|
||||||
fmt.Printf("Error running application: %s\n", err)
|
// fmt.Printf("Error running application: %s\n", err)
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
// Sets up a "Finder" used to navigate the databases, tables, and columns.
|
//// Sets up a "Finder" used to navigate the databases, tables, and columns.
|
||||||
func finder(connString string) {
|
//func finder(connString string) {
|
||||||
// Create the basic objects.
|
// // Create the basic objects.
|
||||||
databases := tview.NewList().ShowSecondaryText(false)
|
// databases := tview.NewList().ShowSecondaryText(false)
|
||||||
databases.SetBorder(true).SetTitle("Databases")
|
// databases.SetBorder(true).SetTitle("Databases")
|
||||||
columns := tview.NewTable().SetBorders(true)
|
// columns := tview.NewTable().SetBorders(true)
|
||||||
columns.SetBorder(true).SetTitle("Columns")
|
// columns.SetBorder(true).SetTitle("Columns")
|
||||||
tables := tview.NewList()
|
// tables := tview.NewList()
|
||||||
tables.ShowSecondaryText(false).
|
// tables.ShowSecondaryText(false).
|
||||||
SetDoneFunc(func() {
|
// SetDoneFunc(func() {
|
||||||
tables.Clear()
|
// tables.Clear()
|
||||||
columns.Clear()
|
// columns.Clear()
|
||||||
app.SetFocus(databases)
|
// app.SetFocus(databases)
|
||||||
})
|
// })
|
||||||
tables.SetBorder(true).SetTitle("Tables")
|
// tables.SetBorder(true).SetTitle("Tables")
|
||||||
|
//
|
||||||
// Create the layout.
|
// // Create the layout.
|
||||||
flex := tview.NewFlex().
|
// flex := tview.NewFlex().
|
||||||
AddItem(databases, 0, 1, true).
|
// AddItem(databases, 0, 1, true).
|
||||||
AddItem(tables, 0, 1, false).
|
// AddItem(tables, 0, 1, false).
|
||||||
AddItem(columns, 0, 3, false)
|
// AddItem(columns, 0, 3, false)
|
||||||
|
//
|
||||||
// We keep one connection pool per database.
|
// // We keep one connection pool per database.
|
||||||
dbMutex := sync.Mutex{}
|
// dbMutex := sync.Mutex{}
|
||||||
dbs := make(map[string]*sql.DB)
|
// dbs := make(map[string]*sql.DB)
|
||||||
getDB := func(database string) *sql.DB {
|
// getDB := func(database string) *sql.DB {
|
||||||
// Connect to a new database.
|
// // Connect to a new database.
|
||||||
dbMutex.Lock()
|
// dbMutex.Lock()
|
||||||
defer dbMutex.Unlock()
|
// defer dbMutex.Unlock()
|
||||||
if db, ok := dbs[database]; ok {
|
// if db, ok := dbs[database]; ok {
|
||||||
return db
|
// return db
|
||||||
}
|
// }
|
||||||
db, err := sql.Open("postgres", connString)
|
// db, err := sql.Open("postgres", connString)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
dbs[database] = db
|
// dbs[database] = db
|
||||||
return db
|
// return db
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Get a list of all databases.
|
// // Get a list of all databases.
|
||||||
generalDB, err := sql.Open("postgres", connString)
|
// generalDB, err := sql.Open("postgres", connString)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
defer generalDB.Close() // We really close the DB because we only use it for this one query.
|
// defer generalDB.Close() // We really close the DB because we only use it for this one query.
|
||||||
rows, err := generalDB.Query("select datname from pg_database where datistemplate = false")
|
// rows, err := generalDB.Query("select datname from pg_database where datistemplate = false")
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
defer rows.Close()
|
// defer rows.Close()
|
||||||
for rows.Next() {
|
// for rows.Next() {
|
||||||
var dbName string
|
// var dbName string
|
||||||
if err := rows.Scan(&dbName); err != nil {
|
// if err := rows.Scan(&dbName); err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
databases.AddItem(dbName, "", 0, func() {
|
// databases.AddItem(dbName, "", 0, func() {
|
||||||
// A database was selected. Show all of its tables.
|
// // A database was selected. Show all of its tables.
|
||||||
columns.Clear()
|
// columns.Clear()
|
||||||
tables.Clear()
|
// tables.Clear()
|
||||||
db := getDB(dbName)
|
// db := getDB(dbName)
|
||||||
t, err := db.Query("select table_name from information_schema.tables where table_schema not in ('information_schema','pg_catalog')")
|
// t, err := db.Query("select table_name from information_schema.tables where table_schema not in ('information_schema','pg_catalog')")
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
defer t.Close()
|
// defer t.Close()
|
||||||
for t.Next() {
|
// for t.Next() {
|
||||||
var tableName string
|
// var tableName string
|
||||||
if err := t.Scan(&tableName); err != nil {
|
// if err := t.Scan(&tableName); err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
tables.AddItem(tableName, "", 0, nil)
|
// tables.AddItem(tableName, "", 0, nil)
|
||||||
}
|
// }
|
||||||
if err := t.Err(); err != nil {
|
// if err := t.Err(); err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
app.SetFocus(tables)
|
// app.SetFocus(tables)
|
||||||
|
//
|
||||||
// When the user navigates to a table, show its columns.
|
// // When the user navigates to a table, show its columns.
|
||||||
tables.SetChangedFunc(func(i int, tableName string, t string, s rune) {
|
// tables.SetChangedFunc(func(i int, tableName string, t string, s rune) {
|
||||||
// A table was selected. Show its columns.
|
// // A table was selected. Show its columns.
|
||||||
columns.Clear()
|
// columns.Clear()
|
||||||
c, err := db.Query(`
|
// c, err := db.Query(`
|
||||||
select
|
// select
|
||||||
c.column_name,
|
// c.column_name,
|
||||||
c.is_nullable,
|
// c.is_nullable,
|
||||||
c.data_type,
|
// c.data_type,
|
||||||
c.character_maximum_length,
|
// c.character_maximum_length,
|
||||||
c.numeric_precision,
|
// c.numeric_precision,
|
||||||
c.numeric_scale,
|
// c.numeric_scale,
|
||||||
c.ordinal_position,
|
// c.ordinal_position,
|
||||||
tc.constraint_type pkey
|
// tc.constraint_type pkey
|
||||||
from
|
// from
|
||||||
information_schema.columns c
|
// information_schema.columns c
|
||||||
left join
|
// left join
|
||||||
information_schema.constraint_column_usage as ccu
|
// information_schema.constraint_column_usage as ccu
|
||||||
on
|
// on
|
||||||
c.table_schema = ccu.table_schema
|
// c.table_schema = ccu.table_schema
|
||||||
and c.table_name = ccu.table_name
|
// and c.table_name = ccu.table_name
|
||||||
and c.column_name = ccu.column_name
|
// and c.column_name = ccu.column_name
|
||||||
left join
|
// left join
|
||||||
information_schema.table_constraints as tc
|
// information_schema.table_constraints as tc
|
||||||
on
|
// on
|
||||||
ccu.constraint_schema = tc.constraint_schema
|
// ccu.constraint_schema = tc.constraint_schema
|
||||||
and ccu.constraint_name = tc.constraint_name
|
// and ccu.constraint_name = tc.constraint_name
|
||||||
where
|
// where
|
||||||
c.table_schema not in ('information_schema','pg_catalog')
|
// c.table_schema not in ('information_schema','pg_catalog')
|
||||||
and c.table_name = $1
|
// and c.table_name = $1
|
||||||
`, tableName)
|
// `, tableName)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
var l logger.Log
|
// var l logger.Log
|
||||||
l = logger.Log{"error", logrus.Fields{"database": err.Error() }, "an error occured in view."}
|
// l = logger.Log{"error", logrus.Fields{"database": err.Error()}, "an error occured in view."}
|
||||||
logger.Lgr(&l)
|
// logger.Lgr(&l)
|
||||||
}
|
// }
|
||||||
defer c.Close()
|
// defer c.Close()
|
||||||
columns.SetCell(0, 0, &tview.TableCell{Text: "Name", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
// columns.SetCell(0, 0, &tview.TableCell{Text: "Name", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
||||||
SetCell(0, 1, &tview.TableCell{Text: "Type", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
// SetCell(0, 1, &tview.TableCell{Text: "Type", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
||||||
SetCell(0, 2, &tview.TableCell{Text: "Size", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
// SetCell(0, 2, &tview.TableCell{Text: "Size", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
||||||
SetCell(0, 3, &tview.TableCell{Text: "Null", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
// SetCell(0, 3, &tview.TableCell{Text: "Null", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
|
||||||
SetCell(0, 4, &tview.TableCell{Text: "Constraint", Align: tview.AlignCenter, Color: tcell.ColorYellow})
|
// SetCell(0, 4, &tview.TableCell{Text: "Constraint", Align: tview.AlignCenter, Color: tcell.ColorYellow})
|
||||||
for c.Next() {
|
// for c.Next() {
|
||||||
var (
|
// var (
|
||||||
columnName, isNullable, dataType string
|
// columnName, isNullable, dataType string
|
||||||
constraintType sql.NullString
|
// constraintType sql.NullString
|
||||||
size, numericPrecision, numericScale sql.NullInt64
|
// size, numericPrecision, numericScale sql.NullInt64
|
||||||
ordinalPosition int
|
// ordinalPosition int
|
||||||
)
|
// )
|
||||||
if err := c.Scan(&columnName,
|
// if err := c.Scan(&columnName,
|
||||||
&isNullable,
|
// &isNullable,
|
||||||
&dataType,
|
// &dataType,
|
||||||
&size,
|
// &size,
|
||||||
&numericPrecision,
|
// &numericPrecision,
|
||||||
&numericScale,
|
// &numericScale,
|
||||||
&ordinalPosition,
|
// &ordinalPosition,
|
||||||
&constraintType,
|
// &constraintType,
|
||||||
); err != nil {
|
// ); err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
sizeText := ""
|
// sizeText := ""
|
||||||
if size.Valid {
|
// if size.Valid {
|
||||||
sizeText = strconv.Itoa(int(size.Int64))
|
// sizeText = strconv.Itoa(int(size.Int64))
|
||||||
} else if numericPrecision.Valid {
|
// } else if numericPrecision.Valid {
|
||||||
sizeText = strconv.Itoa(int(numericPrecision.Int64))
|
// sizeText = strconv.Itoa(int(numericPrecision.Int64))
|
||||||
if numericScale.Valid {
|
// if numericScale.Valid {
|
||||||
sizeText += "," + strconv.Itoa(int(numericScale.Int64))
|
// sizeText += "," + strconv.Itoa(int(numericScale.Int64))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
color := tcell.ColorWhite
|
// color := tcell.ColorWhite
|
||||||
if constraintType.Valid {
|
// if constraintType.Valid {
|
||||||
color = map[string]tcell.Color{
|
// color = map[string]tcell.Color{
|
||||||
"CHECK": tcell.ColorGreen,
|
// "CHECK": tcell.ColorGreen,
|
||||||
"FOREIGN KEY": tcell.ColorDarkMagenta,
|
// "FOREIGN KEY": tcell.ColorDarkMagenta,
|
||||||
"PRIMARY KEY": tcell.ColorRed,
|
// "PRIMARY KEY": tcell.ColorRed,
|
||||||
"UNIQUE": tcell.ColorDarkCyan,
|
// "UNIQUE": tcell.ColorDarkCyan,
|
||||||
}[constraintType.String]
|
// }[constraintType.String]
|
||||||
}
|
// }
|
||||||
columns.SetCell(ordinalPosition, 0, &tview.TableCell{Text: columnName, Color: color}).
|
// columns.SetCell(ordinalPosition, 0, &tview.TableCell{Text: columnName, Color: color}).
|
||||||
SetCell(ordinalPosition, 1, &tview.TableCell{Text: dataType, Color: color}).
|
// SetCell(ordinalPosition, 1, &tview.TableCell{Text: dataType, Color: color}).
|
||||||
SetCell(ordinalPosition, 2, &tview.TableCell{Text: sizeText, Align: tview.AlignRight, Color: color}).
|
// SetCell(ordinalPosition, 2, &tview.TableCell{Text: sizeText, Align: tview.AlignRight, Color: color}).
|
||||||
SetCell(ordinalPosition, 3, &tview.TableCell{Text: isNullable, Align: tview.AlignRight, Color: color}).
|
// SetCell(ordinalPosition, 3, &tview.TableCell{Text: isNullable, Align: tview.AlignRight, Color: color}).
|
||||||
SetCell(ordinalPosition, 4, &tview.TableCell{Text: constraintType.String, Align: tview.AlignLeft, Color: color})
|
// SetCell(ordinalPosition, 4, &tview.TableCell{Text: constraintType.String, Align: tview.AlignLeft, Color: color})
|
||||||
}
|
// }
|
||||||
if err := c.Err(); err != nil {
|
// if err := c.Err(); err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
tables.SetCurrentItem(0) // Trigger the initial selection.
|
// tables.SetCurrentItem(0) // Trigger the initial selection.
|
||||||
|
//
|
||||||
// When the user selects a table, show its content.
|
// // When the user selects a table, show its content.
|
||||||
tables.SetSelectedFunc(func(i int, tableName string, t string, s rune) {
|
// tables.SetSelectedFunc(func(i int, tableName string, t string, s rune) {
|
||||||
content(db, dbName, tableName)
|
// content(db, dbName, tableName)
|
||||||
})
|
// })
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
if err := rows.Err(); err != nil {
|
// if err := rows.Err(); err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Set up the pages and show the Finder.
|
// // Set up the panels and show the Finder.
|
||||||
pages = tview.NewPages().
|
// panels = tview.NewPages().
|
||||||
AddPage(finderPage, flex, true, true)
|
// AddPage(finderPage, flex, true, true)
|
||||||
app.SetRoot(pages, true)
|
// app.SetRoot(panels, true)
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
// Shows the contents of the given table.
|
//// Shows the contents of the given table.
|
||||||
func content(db *sql.DB, dbName, tableName string) {
|
//func content(db *sql.DB, dbName, tableName string) {
|
||||||
finderFocus = app.GetFocus()
|
// finderFocus = app.GetFocus()
|
||||||
|
//
|
||||||
// If this page already exists, just show it.
|
// // If this page already exists, just show it.
|
||||||
if pages.HasPage(dbName + "." + tableName) {
|
// if panels.HasPage(dbName + "." + tableName) {
|
||||||
pages.SwitchToPage(dbName + "." + tableName)
|
// panels.SwitchToPage(dbName + "." + tableName)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
var l logger.Log
|
// var l logger.Log
|
||||||
l = logger.Log{"info", logrus.Fields{"database": tableName }, "selected table to view"}
|
// l = logger.Log{"info", logrus.Fields{"database": tableName}, "selected table to view"}
|
||||||
logger.Lgr(&l)
|
// logger.Lgr(&l)
|
||||||
var schemaName string
|
// var schemaName string
|
||||||
err := db.QueryRow(fmt.Sprintf("select table_schema from information_schema.tables where table_schema not in ('information_schema','pg_catalog') and table_name = '%s'", tableName)).Scan(&schemaName)
|
// err := db.QueryRow(fmt.Sprintf("select table_schema from information_schema.tables where table_schema not in ('information_schema','pg_catalog') and table_name = '%s'", tableName)).Scan(&schemaName)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// We display the data in a table embedded in a frame.
|
// // We display the data in a table embedded in a frame.
|
||||||
table := tview.NewTable().
|
// table := tview.NewTable().
|
||||||
SetFixed(1, 0).
|
// SetFixed(1, 0).
|
||||||
SetBordersColor(tcell.ColorYellow)
|
// SetBordersColor(tcell.ColorYellow)
|
||||||
frame := tview.NewFrame(table).
|
// frame := tview.NewFrame(table).
|
||||||
SetBorders(0, 0, 0, 0, 0, 0)
|
// SetBorders(0, 0, 0, 0, 0, 0)
|
||||||
frame.SetBorder(true).
|
// frame.SetBorder(true).
|
||||||
SetTitle(fmt.Sprintf(`Contents of table "%s.%s"`,schemaName, tableName))
|
// SetTitle(fmt.Sprintf(`Contents of table "%s.%s"`, schemaName, tableName))
|
||||||
|
//
|
||||||
// How many rows does this table have?
|
// // How many rows does this table have?
|
||||||
var rowCount int
|
// var rowCount int
|
||||||
err = db.QueryRow(fmt.Sprintf("select count(*) from %s.%s", schemaName, tableName)).Scan(&rowCount)
|
// err = db.QueryRow(fmt.Sprintf("select count(*) from %s.%s", schemaName, tableName)).Scan(&rowCount)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Load a batch of rows.
|
// // Load a batch of rows.
|
||||||
loadRows := func(offset int) {
|
// loadRows := func(offset int) {
|
||||||
rows, err := db.Query(fmt.Sprintf("select * from %s.%s limit $1 offset $2", schemaName, tableName), batchSize, offset)
|
// rows, err := db.Query(fmt.Sprintf("select * from %s.%s limit $1 offset $2", schemaName, tableName), batchSize, offset)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
defer rows.Close()
|
// defer rows.Close()
|
||||||
|
//
|
||||||
// The first row in the table is the list of column names.
|
// // The first row in the table is the list of column names.
|
||||||
columnNames, err := rows.Columns()
|
// columnNames, err := rows.Columns()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
for index, name := range columnNames {
|
// for index, name := range columnNames {
|
||||||
table.SetCell(0, index, &tview.TableCell{Text: name, Align: tview.AlignCenter, Color: tcell.ColorYellow})
|
// table.SetCell(0, index, &tview.TableCell{Text: name, Align: tview.AlignCenter, Color: tcell.ColorYellow})
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Read the rows.
|
// // Read the rows.
|
||||||
columns := make([]interface{}, len(columnNames))
|
// columns := make([]interface{}, len(columnNames))
|
||||||
columnPointers := make([]interface{}, len(columns))
|
// columnPointers := make([]interface{}, len(columns))
|
||||||
for index := range columnPointers {
|
// for index := range columnPointers {
|
||||||
columnPointers[index] = &columns[index]
|
// columnPointers[index] = &columns[index]
|
||||||
}
|
// }
|
||||||
for rows.Next() {
|
// for rows.Next() {
|
||||||
// Read the columns.
|
// // Read the columns.
|
||||||
err := rows.Scan(columnPointers...)
|
// err := rows.Scan(columnPointers...)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Transfer them to the table.
|
// // Transfer them to the table.
|
||||||
row := table.GetRowCount()
|
// row := table.GetRowCount()
|
||||||
for index, column := range columns {
|
// for index, column := range columns {
|
||||||
switch value := column.(type) {
|
// switch value := column.(type) {
|
||||||
case int64:
|
// case int64:
|
||||||
table.SetCell(row, index, &tview.TableCell{Text: strconv.Itoa(int(value)), Align: tview.AlignRight, Color: tcell.ColorDarkCyan})
|
// table.SetCell(row, index, &tview.TableCell{Text: strconv.Itoa(int(value)), Align: tview.AlignRight, Color: tcell.ColorDarkCyan})
|
||||||
case float64:
|
// case float64:
|
||||||
table.SetCell(row, index, &tview.TableCell{Text: strconv.FormatFloat(value, 'f', 2, 64), Align: tview.AlignRight, Color: tcell.ColorDarkCyan})
|
// table.SetCell(row, index, &tview.TableCell{Text: strconv.FormatFloat(value, 'f', 2, 64), Align: tview.AlignRight, Color: tcell.ColorDarkCyan})
|
||||||
case string:
|
// case string:
|
||||||
table.SetCellSimple(row, index, value)
|
// table.SetCellSimple(row, index, value)
|
||||||
case time.Time:
|
// case time.Time:
|
||||||
t := value.Format("2006-01-02")
|
// t := value.Format("2006-01-02")
|
||||||
table.SetCell(row, index, &tview.TableCell{Text: t, Align: tview.AlignRight, Color: tcell.ColorDarkMagenta})
|
// table.SetCell(row, index, &tview.TableCell{Text: t, Align: tview.AlignRight, Color: tcell.ColorDarkMagenta})
|
||||||
case []uint8:
|
// case []uint8:
|
||||||
str := make([]byte, len(value))
|
// str := make([]byte, len(value))
|
||||||
for index, num := range value {
|
// for index, num := range value {
|
||||||
str[index] = byte(num)
|
// str[index] = byte(num)
|
||||||
}
|
// }
|
||||||
table.SetCell(row, index, &tview.TableCell{Text: string(str), Align: tview.AlignRight, Color: tcell.ColorGreen})
|
// table.SetCell(row, index, &tview.TableCell{Text: string(str), Align: tview.AlignRight, Color: tcell.ColorGreen})
|
||||||
case nil:
|
// case nil:
|
||||||
table.SetCell(row, index, &tview.TableCell{Text: "NULL", Align: tview.AlignCenter, Color: tcell.ColorRed})
|
// table.SetCell(row, index, &tview.TableCell{Text: "NULL", Align: tview.AlignCenter, Color: tcell.ColorRed})
|
||||||
default:
|
// default:
|
||||||
// We've encountered a type that we don't know yet.
|
// // We've encountered a type that we don't know yet.
|
||||||
t := reflect.TypeOf(value)
|
// t := reflect.TypeOf(value)
|
||||||
str := "?nil?"
|
// str := "?nil?"
|
||||||
if t != nil {
|
// if t != nil {
|
||||||
str = "?" + t.String() + "?"
|
// str = "?" + t.String() + "?"
|
||||||
}
|
// }
|
||||||
table.SetCellSimple(row, index, str)
|
// table.SetCellSimple(row, index, str)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if err := rows.Err(); err != nil {
|
// if err := rows.Err(); err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Show how much we've loaded.
|
// // Show how much we've loaded.
|
||||||
frame.Clear()
|
// frame.Clear()
|
||||||
loadMore := ""
|
// loadMore := ""
|
||||||
if table.GetRowCount()-1 < rowCount {
|
// if table.GetRowCount()-1 < rowCount {
|
||||||
loadMore = " - press Enter to load more"
|
// loadMore = " - press Enter to load more"
|
||||||
}
|
// }
|
||||||
loadMore = fmt.Sprintf("Loaded %d of %d rows%s. esc to return to previous menu", table.GetRowCount()-1, rowCount, loadMore)
|
// loadMore = fmt.Sprintf("Loaded %d of %d rows%s. esc to return to previous menu", table.GetRowCount()-1, rowCount, loadMore)
|
||||||
frame.AddText(loadMore, false, tview.AlignCenter, tcell.ColorYellow)
|
// frame.AddText(loadMore, false, tview.AlignCenter, tcell.ColorYellow)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Load the first batch of rows.
|
// // Load the first batch of rows.
|
||||||
loadRows(0)
|
// loadRows(0)
|
||||||
|
//
|
||||||
// Handle key presses.
|
// // Handle key presses.
|
||||||
table.SetDoneFunc(func(key tcell.Key) {
|
// table.SetDoneFunc(func(key tcell.Key) {
|
||||||
switch key {
|
// switch key {
|
||||||
case tcell.KeyEscape:
|
// case tcell.KeyEscape:
|
||||||
// Go back to Finder.
|
// // Go back to Finder.
|
||||||
pages.SwitchToPage(finderPage)
|
// panels.SwitchToPage(finderPage)
|
||||||
if finderFocus != nil {
|
// if finderFocus != nil {
|
||||||
app.SetFocus(finderFocus)
|
// app.SetFocus(finderFocus)
|
||||||
}
|
// }
|
||||||
case tcell.KeyEnter:
|
// case tcell.KeyEnter:
|
||||||
// Load the next batch of rows.
|
// // Load the next batch of rows.
|
||||||
loadRows(table.GetRowCount() - 1)
|
// loadRows(table.GetRowCount() - 1)
|
||||||
table.ScrollToEnd()
|
// table.ScrollToEnd()
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
// Add a new page and show it.
|
// // Add a new page and show it.
|
||||||
pages.AddPage(dbName+"."+tableName, frame, true, true)
|
// panels.AddPage(dbName+"."+tableName, frame, true, true)
|
||||||
}
|
//}
|
||||||
|
|||||||
@ -1,6 +1,15 @@
|
|||||||
package gui
|
package gui
|
||||||
|
|
||||||
import "github.com/rivo/tview"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"shiny-pancake/logger"
|
||||||
|
|
||||||
|
"shiny-pancake/internal/database"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
tview "gitlab.com/tslocum/cview"
|
||||||
|
)
|
||||||
|
|
||||||
type panels struct {
|
type panels struct {
|
||||||
currentPanel int
|
currentPanel int
|
||||||
@ -23,8 +32,84 @@ func newState() *state {
|
|||||||
|
|
||||||
type Gui struct {
|
type Gui struct {
|
||||||
app *tview.Application
|
app *tview.Application
|
||||||
pages *tview.Pages
|
panels *tview.Panels
|
||||||
state *state
|
state *state
|
||||||
db *db.Database
|
db *database.Database
|
||||||
//statsLocations *statsLocations
|
}
|
||||||
|
|
||||||
|
func New(db *database.Database) *Gui {
|
||||||
|
return &Gui{
|
||||||
|
app: tview.NewApplication(),
|
||||||
|
panels: tview.NewPanels(),
|
||||||
|
state: newState(),
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Start start application
|
||||||
|
func (g *Gui) Start() error {
|
||||||
|
g.initPanels()
|
||||||
|
var l logger.Log
|
||||||
|
l = logger.Log{"info", logrus.Fields{"init" : "ran"}, "got this far"}
|
||||||
|
logger.Lgr(&l)
|
||||||
|
if err := g.app.Run(); err != nil {
|
||||||
|
g.app.Stop()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gui) Stop() {
|
||||||
|
g.app.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page "definitions"
|
||||||
|
|
||||||
|
func (g *Gui) sessionPanel() *activeSessions {
|
||||||
|
for _, panel := range g.state.panels.panel {
|
||||||
|
if panel.name() == `activeSessions` {
|
||||||
|
return panel.(*activeSessions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (g *Gui) initPanels() {
|
||||||
|
|
||||||
|
g.state.tabBar = newTabBar()
|
||||||
|
|
||||||
|
// Page definitions
|
||||||
|
s := newSessions(g)
|
||||||
|
var l logger.Log
|
||||||
|
l = logger.Log{"info", logrus.Fields{"initPanels" : "ran"}, "got this far"}
|
||||||
|
logger.Lgr(&l)
|
||||||
|
|
||||||
|
/*
|
||||||
|
// NOTE: I would really like to get this working as it would be far neater.
|
||||||
|
// The issue is with the three panels being of different types.
|
||||||
|
// cannot use pg (type panel) as type tview.Primitive in argument to g.panels.AddPage:
|
||||||
|
// panel does not implement tview.Primitive (missing Blur method)
|
||||||
|
for idx, pg := range []panel{trips, cavers, caves} {
|
||||||
|
name := pg.name()
|
||||||
|
g.panels.AddPage(name, pg, true, idx == 0)
|
||||||
|
fmt.Fprintf(g.state.tabBar, ` %d ["%d"][darkcyan]%s[white][""] `, idx+1, idx, strings.Title(name))
|
||||||
|
}
|
||||||
|
g.state.tabBar.Highlight("0")
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add panels to the "book"
|
||||||
|
g.panels.AddPanel(`activeSessions`, s, true, true)
|
||||||
|
fmt.Fprintf(g.state.tabBar, ` ["%d"]%d %s[""] `, 0, 1, strings.Title(s.name()))
|
||||||
|
|
||||||
|
g.state.tabBar.Highlight("0")
|
||||||
|
|
||||||
|
// Panels
|
||||||
|
|
||||||
|
g.state.panels.panel = append(g.state.panels.panel, s)
|
||||||
|
|
||||||
|
|
||||||
|
g.app.SetRoot(g.panels, true)
|
||||||
}
|
}
|
||||||
18
internal/gui/monitoring.go
Normal file
18
internal/gui/monitoring.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package gui
|
||||||
|
|
||||||
|
//func (g *Gui) startMonitoring() {
|
||||||
|
// stop := make(chan int, 1)
|
||||||
|
// g.state.stopChans["activeSessions"] = stop
|
||||||
|
// go g.sessionPanel().monitoringSessions(g)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (g *Gui) stopMonitoring() {
|
||||||
|
// g.state.stopChans["activeSessions"] <- 1
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
|
/*func (g *Gui) updateTask() {
|
||||||
|
g.app.QueueUpdateDraw(func() {
|
||||||
|
g.caversPanel().setEntries(g) // REVIEW: Why is this just people ?
|
||||||
|
})
|
||||||
|
}*/
|
||||||
9
internal/gui/panel.go
Normal file
9
internal/gui/panel.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package gui
|
||||||
|
|
||||||
|
type panel interface {
|
||||||
|
name() string
|
||||||
|
entries(*Gui)
|
||||||
|
//setEntries(*Gui)
|
||||||
|
//focus(*Gui)
|
||||||
|
//unfocus()
|
||||||
|
}
|
||||||
46
internal/gui/sessions.go
Normal file
46
internal/gui/sessions.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
tview "gitlab.com/tslocum/cview"
|
||||||
|
"shiny-pancake/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type resources struct {
|
||||||
|
ActSess []*model.Session
|
||||||
|
//statsLocations []*model.Statistic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type activeSessions struct {
|
||||||
|
*tview.Table
|
||||||
|
sn chan *model.Session
|
||||||
|
filterCol, filterTerm string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func newSessions(g *Gui) *activeSessions {
|
||||||
|
sess := &activeSessions{
|
||||||
|
Table: tview.NewTable(),
|
||||||
|
sn: make(chan *model.Session),
|
||||||
|
}
|
||||||
|
|
||||||
|
sess.SetBorder(true)
|
||||||
|
sess.entries(g)
|
||||||
|
return sess
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *activeSessions) name() string {
|
||||||
|
return `activeSessions`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func (t *activeSessions) entries(g *Gui) {
|
||||||
|
sss, err := g.db.UserSessions()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
g.state.resources.ActSess = sss
|
||||||
|
}
|
||||||
|
|
||||||
10
internal/gui/tabbar.go
Normal file
10
internal/gui/tabbar.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package gui
|
||||||
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
tview "gitlab.com/tslocum/cview"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTabBar() *tview.TextView {
|
||||||
|
return tview.NewTextView()
|
||||||
|
}
|
||||||
13
internal/model/forms.go
Normal file
13
internal/model/forms.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type HostDetails struct {
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
DatabaseName string `json:"databaseName"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
Username string
|
||||||
|
Count int
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user