Skip to content

Commit

Permalink
improve skywire cli tp tree (#1817)
Browse files Browse the repository at this point in the history
* improve tp tree subcommand
* exit on found both keys
* additional small improvements
* update vendor
* vendor dmsg v1.3.21
  • Loading branch information
0pcom authored Apr 26, 2024
1 parent a00b5dc commit f92b557
Show file tree
Hide file tree
Showing 346 changed files with 47,635 additions and 15 deletions.
190 changes: 179 additions & 11 deletions cmd/skywire-cli/commands/tp/tp.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,18 @@ var (
sortedEdgeKeys []string
utURL string
tpdURL string
rootNode string
lastNode string
rootnode cipher.PubKey
lastnode cipher.PubKey
cacheFileTPD string
cacheFileUT string
padSpaces int
isStats bool
rawData bool
refinedData bool
noFilterOnline bool
onlyOnline bool
transportType string
timeout time.Duration
rpk string
Expand Down Expand Up @@ -401,11 +406,15 @@ func (t *transportID) Set(s string) error {
var RootCmd = tpCmd

func init() {

treeCmd.Flags().StringVarP(&rootNode, "source", "k", "", "root node ; defaults to visor with most transports")
treeCmd.Flags().StringVarP(&lastNode, "dest", "d", "", "map route between source and dest")
treeCmd.Flags().StringVarP(&tpdURL, "tpdurl", "a", utilenv.TpDiscAddr, "transport discovery url")
treeCmd.Flags().StringVarP(&utURL, "uturl", "w", utilenv.UptimeTrackerAddr, "uptime tracker url")
treeCmd.Flags().BoolVarP(&rawData, "raw", "r", false, "print raw json data")
treeCmd.Flags().BoolVarP(&refinedData, "pretty", "p", false, "print pretty json data")
treeCmd.Flags().BoolVarP(&noFilterOnline, "noton", "o", false, "do not filter by online status in UT")
treeCmd.Flags().BoolVarP(&onlyOnline, "good", "g", false, "do not display transports for offline visors")
treeCmd.Flags().StringVar(&cacheFileTPD, "cft", os.TempDir()+"/tpd.json", "TPD cache file location")
treeCmd.Flags().StringVar(&cacheFileUT, "cfu", os.TempDir()+"/ut.json", "UT cache file location.")
treeCmd.Flags().IntVarP(&cacheFilesAge, "cfa", "m", 5, "update cache files if older than n minutes")
Expand All @@ -419,6 +428,22 @@ var treeCmd = &cobra.Command{
Short: "tree map of transports on the skywire network",
Long: fmt.Sprintf("display a tree representation of transports from TPD\n\n%v/all-transports\n\nSet cache file location to \"\" to avoid using cache files", utilenv.TpDiscAddr),
Run: func(cmd *cobra.Command, args []string) {
if rootNode != "" {
err := rootnode.Set(rootNode)
if err != nil {
internal.PrintFatalError(cmd.Flags(), errors.New("invalid source or root node public key"))
}
if lastNode != "" {
err := lastnode.Set(lastNode)
if err != nil {
internal.PrintFatalError(cmd.Flags(), errors.New("invalid dest or last node public key"))
}
}
} else {
if lastNode != "" {
internal.PrintFatalError(cmd.Flags(), errors.New("must specify source or root node public key if dest or last node key is specified"))
}
}
tps := internal.GetData(cacheFileTPD, tpdURL+"/all-transports", cacheFilesAge)
if rawData {
script.Echo(tps).Stdout() //nolint
Expand Down Expand Up @@ -450,13 +475,67 @@ var treeCmd = &cobra.Command{
return
}

fmt.Printf("Tree *Online %s %s TPID Type\n", pterm.Black(pterm.BgRed.Sprint("*Offline")), pterm.Red("*Not in UT"))
var usedkeys []string
if onlyOnline {
var onlineSortedEdgeKeys []string
for i, v := range sortedEdgeKeys {
found := false
for _, k := range utkeys {
if strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(k, " ", ""), "\t", ""), "\n", ""), "\"", "") == strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(v, " ", ""), "\t", ""), "\n", ""), "\"", "") {
found = true
break
}
}
if found {
onlineSortedEdgeKeys = append(onlineSortedEdgeKeys, sortedEdgeKeys[i])
} else {
usedkeys = append(usedkeys, sortedEdgeKeys[i])
}
}
sortedEdgeKeys = onlineSortedEdgeKeys
}

fmt.Printf("Tree *Online %s %s %s %s TPID Type\n", pterm.Black(pterm.BgRed.Sprint("*Offline")), pterm.Red("*Not in UT"), pterm.Blue(pterm.BgMagenta.Sprint("*source")), pterm.Magenta(pterm.BgBlue.Sprint("*dest")))
leveledList := pterm.LeveledList{}
if rootNode != "" {
x := -1
for i, v := range sortedEdgeKeys {
if v == `"`+rootnode.String()+`"` {
x = i
break
}
}
if x != -1 {
for i := x; i > 0; i-- {
sortedEdgeKeys[i] = sortedEdgeKeys[i-1]
}
sortedEdgeKeys[0] = `"` + rootnode.String() + `"`
}
if sortedEdgeKeys[0] != `"`+rootnode.String()+`"` {
internal.PrintFatalError(cmd.Flags(), errors.New("specified source or root node public key does not have any transports"))
}
}
if lastNode != "" {
x := -1
for i, v := range sortedEdgeKeys {
if v == `"`+rootnode.String()+`"` {
x = i
break
}
}
if x != -1 {
for i := x; i > 1; i-- {
sortedEdgeKeys[i] = sortedEdgeKeys[i-1]
}
sortedEdgeKeys[1] = `"` + lastnode.String() + `"`
}
if sortedEdgeKeys[1] != `"`+lastnode.String()+`"` {
internal.PrintFatalError(cmd.Flags(), errors.New("specified dest or last node public key does not have any transports"))
}
}
edgeKey := sortedEdgeKeys[0]
leveledList = append(leveledList, pterm.LeveledListItem{Level: 0, Text: filterOnlineStatus(utkeys, offlinekeys, edgeKey)})

var usedkeys []string
usedkeys = append(usedkeys, edgeKey)
var lvl func(n int, k string)
lvl = func(n int, k string) {
Expand Down Expand Up @@ -493,34 +572,117 @@ var treeCmd = &cobra.Command{
}
}
lvl(1, edgeKey)

pterm.DefaultTree.WithRoot(putils.TreeFromLeveledList(leveledList)).Render() //nolint

for _, edgeKey := range sortedEdgeKeys {
found := false
for _, usedKey := range usedkeys {
if usedKey == edgeKey {
found = true
break
}
if lastNode != "" && strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(usedKey, " ", ""), "\t", ""), "\n", ""), "\"", "") == strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(`"`+lastnode.String()+`"`, " ", ""), "\t", ""), "\n", ""), "\"", "") {
found = true
break
}
}
if !found {
leveledList = pterm.LeveledList{}
leveledList = append(leveledList, pterm.LeveledListItem{Level: 0, Text: filterOnlineStatus(utkeys, offlinekeys, edgeKey)})
usedkeys = append(usedkeys, edgeKey)
lvl(1, edgeKey)
pterm.DefaultTree.WithRoot(putils.TreeFromLeveledList(leveledList)).Render() //nolint
if len(leveledList) > 1 {
pterm.DefaultTree.WithRoot(putils.TreeFromLeveledList(leveledList)).Render() //nolint
}
if lastNode != "" {
pterm.Println(pterm.Red("No route from source to dest"))
return
}
}
}
l, _ := script.Echo(tps).JQ(".[] | select(.edges[0] == .edges[1]) | .edges[0] + \""+strings.Repeat(" ", padSpaces)+"\" + .t_id + \" \" + .type").Replace("\"", "").Slice() //nolint
if len(l) > 0 {
pterm.Println(pterm.Red("Self-transports"))
for _, m := range l {
pterm.Println(filterOnlineStatus(utkeys, offlinekeys, m))
if lastNode != "" && rootNode != "" {
x := -1
for i, v := range usedkeys {
if v == `"`+rootnode.String()+`"` {
x = i
break
}
}
if x != -1 {
for i := x; i > 0; i-- {
usedkeys[i] = usedkeys[i-1]
}
usedkeys[0] = `"` + rootnode.String() + `"`
}
if usedkeys[0] != `"`+rootnode.String()+`"` {
internal.PrintFatalError(cmd.Flags(), errors.New("specified source or root node public key does not have any transports"))
}
if lastNode != "" {
x := -1
for i, v := range usedkeys {
if v == `"`+rootnode.String()+`"` {
x = i
break
}
}
if x != -1 {
for i := x; i > 1; i-- {
usedkeys[i] = usedkeys[i-1]
}
usedkeys[1] = `"` + lastnode.String() + `"`
}
if usedkeys[1] != `"`+lastnode.String()+`"` {
internal.PrintFatalError(cmd.Flags(), errors.New("specified dest or last node public key does not have any transports"))
}
}
l, _ := script.Echo(tps).JQ("[.[] | select(.edges | contains([" + usedkeys[0] + "," + usedkeys[1] + "]))]").Slice() //nolint
if len(l) > 0 {
pterm.Println(pterm.Red("Direct route:"))
for _, m := range l {
script.Echo(string(pretty.Color(pretty.Pretty([]byte(m)), nil))).Stdout() //nolint
}
}
/*
var tM tpdMaps
for i, v := range usedkeys {
tM[i].PK = v
}
for i, v := range tM {
l, _ := script.Echo(tps).JQ(".[] | select(.edges[] == " + v + ") | .edges[] | select(. != " + v + ")").Slice() //nolint
for _, m := range l {
if m == v {
continue
}
tM[i].Edges = append(tM[i].Edges,v)
}
}
for i, v := range tM {
for j, w := range v.Edges {
}
}
*/
}
if rootNode == "" && !onlyOnline {
l, _ := script.Echo(tps).JQ(".[] | select(.edges[0] == .edges[1]) | .edges[0] + \""+strings.Repeat(" ", padSpaces)+"\" + .t_id + \" \" + .type").Replace("\"", "").Slice() //nolint
if len(l) > 0 {
pterm.Println(pterm.Red("Self-transports"))
for _, m := range l {
pterm.Println(filterOnlineStatus(utkeys, offlinekeys, m))
}
}
}
},
}

/*
type tpdMap struct {
PK string
Edges []string
}
type tpdMaps []tpdMap
*/
func filterOnlineStatus(utkeys, offlinekeys []string, key string) (lvlN string) {
isOnline, isOffline := false, false
lvlN = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(key, " ", ""), "\t", ""), "\n", ""), "\"", "")
Expand All @@ -543,10 +705,16 @@ func filterOnlineStatus(utkeys, offlinekeys []string, key string) (lvlN string)
isOnline, isOffline = true, false
}
if !isOnline && !isOffline {
lvlN = pterm.Red(strings.ReplaceAll(key, "\"", ""))
lvlN = pterm.Red(lvlN)
}
if isOffline {
lvlN = pterm.Black(pterm.BgRed.Sprint(strings.ReplaceAll(key, "\"", "")))
lvlN = pterm.Black(pterm.BgRed.Sprint(lvlN))
}
if lastNode != "" && strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(`"`+lastnode.String()+`"`, " ", ""), "\t", ""), "\n", ""), "\"", "") == strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(key, " ", ""), "\t", ""), "\n", ""), "\"", "") {
lvlN = pterm.Magenta(pterm.BgBlue.Sprint(lvlN))
}
if rootNode != "" && strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(`"`+rootnode.String()+`"`, " ", ""), "\t", ""), "\n", ""), "\"", "") == strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(key, " ", ""), "\t", ""), "\n", ""), "\"", "") {
lvlN = pterm.Blue(pterm.BgMagenta.Sprint(lvlN))
}
return lvlN
}
96 changes: 96 additions & 0 deletions cmd/skywire-cli/commands/visor/description.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
gotop shows system information in a terminal UI. It can be configured to have
different layouts, color schemes, and widgets, and it is able to show
information from other computers.

Anything you change on the command line can be written to a config file
using the `--write-config` argument, which can then be edited further.
Just get your arguments the way you like, then run gotop again with the same
arguments and the `--write-config` flag, and gotop will persist your
options.

Colorschemes are json files; put them in the config directory (usually
~/.config/gotop/{name}.json) and load them with the `-c {name}` argument.
The keys are:

Fg -- int, foreground color
Bg -- int, background color
BorderLabel -- int, color of widget text
BorderLine -- int, color of borders
CPULines -- array of ints for the colors of lines
BattLines -- array of ints for the colors of lines
MemLines -- array of ints for the colors of lines
ProcCursor -- int, color of the cursor in the process widget
Sparklines -- array of ints for the colors of network usage
DiskBar -- int, color of the disk bars
TempLow -- int, color used for low temperatures
TempHigh -- int, color used for high temperatures

For example:

{ "Fg": 7, "CPULines": [4, 3, 2, 1, 5, 6, 7, 8] }

Colorschemes are referred to by their name minus the .json suffix. More
examples are here:

https://github.com/xxxserxxx/gotop/tree/master/colorschemes

Layout files are plain text files, with widget names on rows roughly representing
a grid. The format is ROWSPAN:WIDGETNAME/COLSPAN. COLSPAN is relative to the
rest of the line, so a line saying "cpu mem/3" will give the CPU widget 25% of
the width, and the memory widget 75% of the width. ROWSPAN is the height of
the widget, so "2:cpu mem" will make the CPU widget 2 rows high, and the memory
widget 1 row high. An example is:

2:cpu
disk/1 2:mem/2
temp
2:net 2:procs

Save your layout under any file name either in the config directory or your current
directory and reference the file name with the `-l` argument. More details about
the rules are here:

https://github.com/xxxserxxx/gotop/blob/master/docs/layouts.md

and examples are here:

https://github.com/xxxserxxx/gotop/tree/master/layouts

gotop can function as both a metrics exporter and viewer. As an exporter, it
exports Prometheus metrics, and it does not handle either encryption or
authentication, and so should be run behind a reverse proxy. When gotop is run
with the `-x` argument, gotop will export metrics on the given port. To try it,
run

gotop -x :8884

and then from another shell, run:

curl http://localhost:8884/metrics

To show these metrics in gotop, instead of curl run:

gotop --remote-url http://localhost:8884/metrics

You will see additional values in your widgets. To monitor remote machines,
run gotop on them with the `-x` export flag behind a reverse proxy such as
Caddy:

myserver.net {
basicauth / gtuser gtpass
reverse-proxy /metrics http://localhost:8884
}

and then on your local gotop:

gotop --remote-url https://gtuser:[email protected]/metrics

Config files, layouts, and color schemes are searched for (in order):

- In the current directory
- In $XDG_CONFIG_DIR/gotop
- In /etc/gotop (on Linux and MacOS)

More information and detailed documentation can found at
https://github.com/xxxserxxx/gotop`

Loading

0 comments on commit f92b557

Please sign in to comment.