mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	Merge pull request #85 from neilalexander/yggdrasilctl
Human-readable formatting in yggdrasilctl
This commit is contained in:
		
						commit
						b10ae51565
					
				
					 2 changed files with 138 additions and 17 deletions
				
			
		| 
						 | 
					@ -44,17 +44,20 @@ func (a *admin) init(c *Core, listenaddr string) {
 | 
				
			||||||
	a.core = c
 | 
						a.core = c
 | 
				
			||||||
	a.listenaddr = listenaddr
 | 
						a.listenaddr = listenaddr
 | 
				
			||||||
	a.addHandler("help", nil, func(in admin_info) (admin_info, error) {
 | 
						a.addHandler("help", nil, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
		handlers := make(map[string][]string)
 | 
							handlers := make(map[string]interface{})
 | 
				
			||||||
		for _, handler := range a.handlers {
 | 
							for _, handler := range a.handlers {
 | 
				
			||||||
			handlers[handler.name] = handler.args
 | 
								handlers[handler.name] = admin_info{"fields": handler.args}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return admin_info{"handlers": handlers}, nil
 | 
							return admin_info{"help": handlers}, nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	a.addHandler("dot", []string{}, func(in admin_info) (admin_info, error) {
 | 
						a.addHandler("dot", []string{}, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
		return admin_info{"dot": string(a.getResponse_dot())}, nil
 | 
							return admin_info{"dot": string(a.getResponse_dot())}, nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	a.addHandler("getSelf", []string{}, func(in admin_info) (admin_info, error) {
 | 
						a.addHandler("getSelf", []string{}, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
		return admin_info{"self": a.getData_getSelf().asMap()}, nil
 | 
							self := a.getData_getSelf().asMap()
 | 
				
			||||||
 | 
							ip := fmt.Sprint(self["ip"])
 | 
				
			||||||
 | 
							delete(self, "ip")
 | 
				
			||||||
 | 
							return admin_info{"self": admin_info{ip: self}}, nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	a.addHandler("getPeers", []string{}, func(in admin_info) (admin_info, error) {
 | 
						a.addHandler("getPeers", []string{}, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
		sort := "ip"
 | 
							sort := "ip"
 | 
				
			||||||
| 
						 | 
					@ -133,14 +136,15 @@ func (a *admin) init(c *Core, listenaddr string) {
 | 
				
			||||||
	a.addHandler("getTunTap", []string{}, func(in admin_info) (r admin_info, e error) {
 | 
						a.addHandler("getTunTap", []string{}, func(in admin_info) (r admin_info, e error) {
 | 
				
			||||||
		defer func() {
 | 
							defer func() {
 | 
				
			||||||
			recover()
 | 
								recover()
 | 
				
			||||||
			r = admin_info{"name": "none"}
 | 
								r = admin_info{"none": admin_info{}}
 | 
				
			||||||
			e = nil
 | 
								e = nil
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return admin_info{
 | 
							return admin_info{
 | 
				
			||||||
			"name":     a.core.tun.iface.Name(),
 | 
								a.core.tun.iface.Name(): admin_info{
 | 
				
			||||||
			"tap_mode": a.core.tun.iface.IsTAP(),
 | 
									"tap_mode": a.core.tun.iface.IsTAP(),
 | 
				
			||||||
			"mtu":      a.core.tun.mtu,
 | 
									"mtu":      a.core.tun.mtu,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	a.addHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in admin_info) (admin_info, error) {
 | 
						a.addHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
| 
						 | 
					@ -162,9 +166,10 @@ func (a *admin) init(c *Core, listenaddr string) {
 | 
				
			||||||
			return admin_info{}, errors.New("Failed to configure adapter")
 | 
								return admin_info{}, errors.New("Failed to configure adapter")
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return admin_info{
 | 
								return admin_info{
 | 
				
			||||||
				"name":     a.core.tun.iface.Name(),
 | 
									a.core.tun.iface.Name(): admin_info{
 | 
				
			||||||
				"tap_mode": a.core.tun.iface.IsTAP(),
 | 
										"tap_mode": a.core.tun.iface.IsTAP(),
 | 
				
			||||||
				"mtu":      ifmtu,
 | 
										"mtu":      ifmtu,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			}, nil
 | 
								}, nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
| 
						 | 
					@ -273,7 +278,7 @@ func (a *admin) handleRequest(conn net.Conn) {
 | 
				
			||||||
					if _, ok := recv[arg]; !ok {
 | 
										if _, ok := recv[arg]; !ok {
 | 
				
			||||||
						send = admin_info{
 | 
											send = admin_info{
 | 
				
			||||||
							"status":    "error",
 | 
												"status":    "error",
 | 
				
			||||||
							"error":     "Expected field missing",
 | 
												"error":     "Expected field missing: " + arg,
 | 
				
			||||||
							"expecting": arg,
 | 
												"expecting": arg,
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						break handlers
 | 
											break handlers
 | 
				
			||||||
| 
						 | 
					@ -432,7 +437,7 @@ func (a *admin) getData_getPeers() []admin_nodeInfo {
 | 
				
			||||||
		info := admin_nodeInfo{
 | 
							info := admin_nodeInfo{
 | 
				
			||||||
			{"ip", net.IP(addr[:]).String()},
 | 
								{"ip", net.IP(addr[:]).String()},
 | 
				
			||||||
			{"port", port},
 | 
								{"port", port},
 | 
				
			||||||
			{"uptime", fmt.Sprint(time.Since(p.firstSeen))},
 | 
								{"uptime", int(time.Since(p.firstSeen).Seconds())},
 | 
				
			||||||
			{"bytes_sent", atomic.LoadUint64(&p.bytesSent)},
 | 
								{"bytes_sent", atomic.LoadUint64(&p.bytesSent)},
 | 
				
			||||||
			{"bytes_recvd", atomic.LoadUint64(&p.bytesRecvd)},
 | 
								{"bytes_recvd", atomic.LoadUint64(&p.bytesRecvd)},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -476,7 +481,7 @@ func (a *admin) getData_getDHT() []admin_nodeInfo {
 | 
				
			||||||
						{"coords", fmt.Sprint(v.coords)},
 | 
											{"coords", fmt.Sprint(v.coords)},
 | 
				
			||||||
						{"bucket", i},
 | 
											{"bucket", i},
 | 
				
			||||||
						{"peer_only", isPeer},
 | 
											{"peer_only", isPeer},
 | 
				
			||||||
						{"last_seen", fmt.Sprint(now.Sub(v.recv))},
 | 
											{"last_seen", int(now.Sub(v.recv).Seconds())},
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					infos = append(infos, info)
 | 
										infos = append(infos, info)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										122
									
								
								yggdrasilctl.go
									
										
									
									
									
								
							
							
						
						
									
										122
									
								
								yggdrasilctl.go
									
										
									
									
									
								
							| 
						 | 
					@ -4,6 +4,7 @@ import "flag"
 | 
				
			||||||
import "fmt"
 | 
					import "fmt"
 | 
				
			||||||
import "strings"
 | 
					import "strings"
 | 
				
			||||||
import "net"
 | 
					import "net"
 | 
				
			||||||
 | 
					import "sort"
 | 
				
			||||||
import "encoding/json"
 | 
					import "encoding/json"
 | 
				
			||||||
import "strconv"
 | 
					import "strconv"
 | 
				
			||||||
import "os"
 | 
					import "os"
 | 
				
			||||||
| 
						 | 
					@ -12,11 +13,12 @@ type admin_info map[string]interface{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	server := flag.String("endpoint", "localhost:9001", "Admin socket endpoint")
 | 
						server := flag.String("endpoint", "localhost:9001", "Admin socket endpoint")
 | 
				
			||||||
 | 
						injson := flag.Bool("json", false, "Output in JSON format")
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
	args := flag.Args()
 | 
						args := flag.Args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(args) == 0 {
 | 
						if len(args) == 0 {
 | 
				
			||||||
		fmt.Println("usage:", os.Args[0], "[-endpoint=localhost:9001] command [key=value] [...]")
 | 
							fmt.Println("usage:", os.Args[0], "[-endpoint=localhost:9001] [-json] command [key=value] [...]")
 | 
				
			||||||
		fmt.Println("example:", os.Args[0], "getPeers")
 | 
							fmt.Println("example:", os.Args[0], "getPeers")
 | 
				
			||||||
		fmt.Println("example:", os.Args[0], "setTunTap name=auto mtu=1500 tap_mode=false")
 | 
							fmt.Println("example:", os.Args[0], "setTunTap name=auto mtu=1500 tap_mode=false")
 | 
				
			||||||
		fmt.Println("example:", os.Args[0], "-endpoint=localhost:9001 getDHT")
 | 
							fmt.Println("example:", os.Args[0], "-endpoint=localhost:9001 getDHT")
 | 
				
			||||||
| 
						 | 
					@ -58,19 +60,133 @@ func main() {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := decoder.Decode(&recv); err == nil {
 | 
						if err := decoder.Decode(&recv); err == nil {
 | 
				
			||||||
 | 
							if recv["status"] == "error" {
 | 
				
			||||||
 | 
								if err, ok := recv["error"]; ok {
 | 
				
			||||||
 | 
									fmt.Println("Error:", err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									fmt.Println("Unspecified error occured")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								os.Exit(1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if _, ok := recv["request"]; !ok {
 | 
							if _, ok := recv["request"]; !ok {
 | 
				
			||||||
			fmt.Println("Missing request")
 | 
								fmt.Println("Missing request in response (malformed response?)")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if _, ok := recv["response"]; !ok {
 | 
							if _, ok := recv["response"]; !ok {
 | 
				
			||||||
			fmt.Println("Missing response")
 | 
								fmt.Println("Missing response body (malformed response?)")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		req := recv["request"].(map[string]interface{})
 | 
							req := recv["request"].(map[string]interface{})
 | 
				
			||||||
		res := recv["response"].(map[string]interface{})
 | 
							res := recv["response"].(map[string]interface{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if *injson {
 | 
				
			||||||
 | 
								if json, err := json.MarshalIndent(res, "", "  "); err == nil {
 | 
				
			||||||
 | 
									fmt.Println(string(json))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								os.Exit(0)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch req["request"] {
 | 
							switch req["request"] {
 | 
				
			||||||
		case "dot":
 | 
							case "dot":
 | 
				
			||||||
			fmt.Println(res["dot"])
 | 
								fmt.Println(res["dot"])
 | 
				
			||||||
 | 
							case "help", "getPeers", "getSwitchPeers", "getDHT", "getSessions":
 | 
				
			||||||
 | 
								maxWidths := make(map[string]int)
 | 
				
			||||||
 | 
								var keyOrder []string
 | 
				
			||||||
 | 
								keysOrdered := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for _, tlv := range res {
 | 
				
			||||||
 | 
									for slk, slv := range tlv.(map[string]interface{}) {
 | 
				
			||||||
 | 
										if !keysOrdered {
 | 
				
			||||||
 | 
											for k := range slv.(map[string]interface{}) {
 | 
				
			||||||
 | 
												keyOrder = append(keyOrder, fmt.Sprint(k))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											sort.Strings(keyOrder)
 | 
				
			||||||
 | 
											keysOrdered = true
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										for k, v := range slv.(map[string]interface{}) {
 | 
				
			||||||
 | 
											if len(fmt.Sprint(slk)) > maxWidths["key"] {
 | 
				
			||||||
 | 
												maxWidths["key"] = len(fmt.Sprint(slk))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if len(fmt.Sprint(v)) > maxWidths[k] {
 | 
				
			||||||
 | 
												maxWidths[k] = len(fmt.Sprint(v))
 | 
				
			||||||
 | 
												if maxWidths[k] < len(k) {
 | 
				
			||||||
 | 
													maxWidths[k] = len(k)
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if len(keyOrder) > 0 {
 | 
				
			||||||
 | 
										fmt.Printf("%-"+fmt.Sprint(maxWidths["key"])+"s  ", "")
 | 
				
			||||||
 | 
										for _, v := range keyOrder {
 | 
				
			||||||
 | 
											fmt.Printf("%-"+fmt.Sprint(maxWidths[v])+"s  ", v)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										fmt.Println()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									for slk, slv := range tlv.(map[string]interface{}) {
 | 
				
			||||||
 | 
										fmt.Printf("%-"+fmt.Sprint(maxWidths["key"])+"s  ", slk)
 | 
				
			||||||
 | 
										for _, k := range keyOrder {
 | 
				
			||||||
 | 
											preformatted := slv.(map[string]interface{})[k]
 | 
				
			||||||
 | 
											var formatted string
 | 
				
			||||||
 | 
											switch k {
 | 
				
			||||||
 | 
											case "bytes_sent", "bytes_recvd":
 | 
				
			||||||
 | 
												formatted = fmt.Sprintf("%d", uint(preformatted.(float64)))
 | 
				
			||||||
 | 
											case "uptime", "last_seen":
 | 
				
			||||||
 | 
												seconds := uint(preformatted.(float64)) % 60
 | 
				
			||||||
 | 
												minutes := uint(preformatted.(float64)/60) % 60
 | 
				
			||||||
 | 
												hours := uint(preformatted.(float64) / 60 / 60)
 | 
				
			||||||
 | 
												formatted = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
 | 
				
			||||||
 | 
											default:
 | 
				
			||||||
 | 
												formatted = fmt.Sprint(preformatted)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											fmt.Printf("%-"+fmt.Sprint(maxWidths[k])+"s  ", formatted)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										fmt.Println()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case "getTunTap", "setTunTap":
 | 
				
			||||||
 | 
								for k, v := range res {
 | 
				
			||||||
 | 
									fmt.Println("Interface name:", k)
 | 
				
			||||||
 | 
									if mtu, ok := v.(map[string]interface{})["mtu"].(float64); ok {
 | 
				
			||||||
 | 
										fmt.Println("Interface MTU:", mtu)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if tap_mode, ok := v.(map[string]interface{})["tap_mode"].(bool); ok {
 | 
				
			||||||
 | 
										fmt.Println("TAP mode:", tap_mode)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case "addPeer", "removePeer", "addAllowedBoxPub", "removeAllowedBoxPub":
 | 
				
			||||||
 | 
								if _, ok := res["added"]; ok {
 | 
				
			||||||
 | 
									for _, v := range res["added"].([]interface{}) {
 | 
				
			||||||
 | 
										fmt.Println("Added:", fmt.Sprint(v))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if _, ok := res["not_added"]; ok {
 | 
				
			||||||
 | 
									for _, v := range res["not_added"].([]interface{}) {
 | 
				
			||||||
 | 
										fmt.Println("Not added:", fmt.Sprint(v))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if _, ok := res["removed"]; ok {
 | 
				
			||||||
 | 
									for _, v := range res["removed"].([]interface{}) {
 | 
				
			||||||
 | 
										fmt.Println("Removed:", fmt.Sprint(v))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if _, ok := res["not_removed"]; ok {
 | 
				
			||||||
 | 
									for _, v := range res["not_removed"].([]interface{}) {
 | 
				
			||||||
 | 
										fmt.Println("Not removed:", fmt.Sprint(v))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case "getAllowedBoxPubs":
 | 
				
			||||||
 | 
								if _, ok := res["allowed_box_pubs"]; !ok {
 | 
				
			||||||
 | 
									fmt.Println("All connections are allowed")
 | 
				
			||||||
 | 
								} else if res["allowed_box_pubs"] == nil {
 | 
				
			||||||
 | 
									fmt.Println("All connections are allowed")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									fmt.Println("Connections are allowed only from the following public box keys:")
 | 
				
			||||||
 | 
									for _, v := range res["allowed_box_pubs"].([]interface{}) {
 | 
				
			||||||
 | 
										fmt.Println("-", v)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			if json, err := json.MarshalIndent(recv["response"], "", "  "); err == nil {
 | 
								if json, err := json.MarshalIndent(recv["response"], "", "  "); err == nil {
 | 
				
			||||||
				fmt.Println(string(json))
 | 
									fmt.Println(string(json))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue