c026299b95
GlobalPinInfo objects carried redundant information (Cid, Peer) that takes space and time to serialize. This has been addressed by having GlobalPinInfo embed PinInfoShort rather than PinInfo. This new types ommits redundant fields.
290 lines
6.3 KiB
Go
290 lines
6.3 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/ipfs/ipfs-cluster/api"
|
|
|
|
peer "github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
humanize "github.com/dustin/go-humanize"
|
|
)
|
|
|
|
type addedOutputQuiet struct {
|
|
*api.AddedOutput
|
|
quiet bool
|
|
}
|
|
|
|
func jsonFormatObject(resp interface{}) {
|
|
switch r := resp.(type) {
|
|
case nil:
|
|
return
|
|
case []*addedOutputQuiet:
|
|
// print original objects as in JSON it makes
|
|
// no sense to have a human "quiet" output
|
|
var actual []*api.AddedOutput
|
|
for _, s := range r {
|
|
actual = append(actual, s.AddedOutput)
|
|
}
|
|
jsonFormatPrint(actual)
|
|
default:
|
|
jsonFormatPrint(resp)
|
|
}
|
|
}
|
|
|
|
func jsonFormatPrint(obj interface{}) {
|
|
j, err := json.MarshalIndent(obj, "", " ")
|
|
checkErr("generating json output", err)
|
|
fmt.Printf("%s\n", j)
|
|
}
|
|
|
|
func textFormatObject(resp interface{}) {
|
|
switch r := resp.(type) {
|
|
case nil:
|
|
return
|
|
case string:
|
|
fmt.Println(resp)
|
|
case *api.ID:
|
|
textFormatPrintID(r)
|
|
case *api.GlobalPinInfo:
|
|
textFormatPrintGPInfo(r)
|
|
case *api.Pin:
|
|
textFormatPrintPin(r)
|
|
case *api.AddedOutput:
|
|
textFormatPrintAddedOutput(r)
|
|
case *addedOutputQuiet:
|
|
textFormatPrintAddedOutputQuiet(r)
|
|
case *api.Version:
|
|
textFormatPrintVersion(r)
|
|
case *api.Error:
|
|
textFormatPrintError(r)
|
|
case *api.Metric:
|
|
textFormatPrintMetric(r)
|
|
case []*api.ID:
|
|
for _, item := range r {
|
|
textFormatObject(item)
|
|
}
|
|
case []*api.GlobalPinInfo:
|
|
for _, item := range r {
|
|
textFormatObject(item)
|
|
}
|
|
case []*api.Pin:
|
|
for _, item := range r {
|
|
textFormatObject(item)
|
|
}
|
|
case []*api.AddedOutput:
|
|
for _, item := range r {
|
|
textFormatObject(item)
|
|
}
|
|
case []*addedOutputQuiet:
|
|
for _, item := range r {
|
|
textFormatObject(item)
|
|
}
|
|
case []*api.Metric:
|
|
for _, item := range r {
|
|
textFormatObject(item)
|
|
}
|
|
case *api.GlobalRepoGC:
|
|
textFormatPrintGlobalRepoGC(r)
|
|
case []string:
|
|
for _, item := range r {
|
|
textFormatObject(item)
|
|
}
|
|
default:
|
|
checkErr("", errors.New("unsupported type returned"))
|
|
}
|
|
}
|
|
|
|
func textFormatPrintID(obj *api.ID) {
|
|
if obj.Error != "" {
|
|
fmt.Printf("%s | ERROR: %s\n", obj.ID.Pretty(), obj.Error)
|
|
return
|
|
}
|
|
|
|
fmt.Printf(
|
|
"%s | %s | Sees %d other peers\n",
|
|
obj.ID.Pretty(),
|
|
obj.Peername,
|
|
len(obj.ClusterPeers)-1,
|
|
)
|
|
|
|
addrs := make(sort.StringSlice, 0, len(obj.Addresses))
|
|
for _, a := range obj.Addresses {
|
|
addrs = append(addrs, a.String())
|
|
}
|
|
addrs.Sort()
|
|
fmt.Println(" > Addresses:")
|
|
for _, a := range addrs {
|
|
fmt.Printf(" - %s\n", a)
|
|
}
|
|
if obj.IPFS.Error != "" {
|
|
fmt.Printf(" > IPFS ERROR: %s\n", obj.IPFS.Error)
|
|
return
|
|
}
|
|
|
|
ipfsAddrs := make(sort.StringSlice, 0, len(obj.Addresses))
|
|
for _, a := range obj.IPFS.Addresses {
|
|
ipfsAddrs = append(ipfsAddrs, a.String())
|
|
}
|
|
ipfsAddrs.Sort()
|
|
fmt.Printf(" > IPFS: %s\n", obj.IPFS.ID.Pretty())
|
|
for _, a := range ipfsAddrs {
|
|
fmt.Printf(" - %s\n", a)
|
|
}
|
|
}
|
|
|
|
func textFormatPrintGPInfo(obj *api.GlobalPinInfo) {
|
|
var b strings.Builder
|
|
|
|
peers := make([]string, 0, len(obj.PeerMap))
|
|
for k := range obj.PeerMap {
|
|
peers = append(peers, k)
|
|
}
|
|
sort.Strings(peers)
|
|
|
|
fmt.Fprintf(&b, "%s", obj.Cid)
|
|
if obj.Name != "" {
|
|
fmt.Fprintf(&b, " | %s", obj.Name)
|
|
}
|
|
|
|
b.WriteString(":\n")
|
|
|
|
for _, k := range peers {
|
|
v := obj.PeerMap[k]
|
|
if len(v.PeerName) > 0 {
|
|
fmt.Fprintf(&b, " > %-20s : %s", v.PeerName, strings.ToUpper(v.Status.String()))
|
|
} else {
|
|
fmt.Fprintf(&b, " > %-20s : %s", k, strings.ToUpper(v.Status.String()))
|
|
}
|
|
if v.Error != "" {
|
|
fmt.Fprintf(&b, ": %s", v.Error)
|
|
}
|
|
txt, _ := v.TS.MarshalText()
|
|
fmt.Fprintf(&b, " | %s\n", txt)
|
|
}
|
|
fmt.Print(b.String())
|
|
}
|
|
|
|
func textFormatPrintVersion(obj *api.Version) {
|
|
fmt.Println(obj.Version)
|
|
}
|
|
|
|
func textFormatPrintPin(obj *api.Pin) {
|
|
t := strings.ToUpper(obj.Type.String())
|
|
if obj.Mode == api.PinModeDirect {
|
|
t = t + "-DIRECT"
|
|
}
|
|
|
|
fmt.Printf("%s | %s | %s | ", obj.Cid, obj.Name, t)
|
|
|
|
if obj.ReplicationFactorMin < 0 {
|
|
fmt.Printf("Repl. Factor: -1 | Allocations: [everywhere]")
|
|
} else {
|
|
sortAlloc := api.PeersToStrings(obj.Allocations)
|
|
sort.Strings(sortAlloc)
|
|
fmt.Printf("Repl. Factor: %d--%d | Allocations: %s",
|
|
obj.ReplicationFactorMin, obj.ReplicationFactorMax,
|
|
sortAlloc)
|
|
}
|
|
var recStr string
|
|
switch obj.MaxDepth {
|
|
case 0:
|
|
recStr = "Direct"
|
|
case -1:
|
|
recStr = "Recursive"
|
|
default:
|
|
recStr = fmt.Sprintf("Recursive-%d", obj.MaxDepth)
|
|
}
|
|
|
|
fmt.Printf(" | %s", recStr)
|
|
|
|
fmt.Printf(" | Metadata:")
|
|
if len(obj.Metadata) == 0 {
|
|
fmt.Printf(" no")
|
|
} else {
|
|
fmt.Printf(" yes")
|
|
}
|
|
expireAt := "Exp: ∞"
|
|
if !obj.ExpireAt.IsZero() {
|
|
expireAt = humanize.Time(obj.ExpireAt)
|
|
}
|
|
fmt.Printf(" | %s\n", expireAt)
|
|
}
|
|
|
|
func textFormatPrintAddedOutput(obj *api.AddedOutput) {
|
|
fmt.Printf("added %s %s\n", obj.Cid, obj.Name)
|
|
}
|
|
|
|
func textFormatPrintAddedOutputQuiet(obj *addedOutputQuiet) {
|
|
if obj.quiet {
|
|
fmt.Printf("%s\n", obj.AddedOutput.Cid)
|
|
} else {
|
|
textFormatPrintAddedOutput(obj.AddedOutput)
|
|
}
|
|
}
|
|
|
|
func textFormatPrintMetric(obj *api.Metric) {
|
|
if obj.Name == "freespace" {
|
|
u, err := strconv.ParseUint(obj.Value, 10, 64)
|
|
checkErr("parsing to uint64", err)
|
|
fmt.Printf("%s | freespace: %s | Expires in: %s\n", peer.Encode(obj.Peer), humanize.Bytes(u), humanize.Time(time.Unix(0, obj.Expire)))
|
|
return
|
|
}
|
|
|
|
fmt.Printf("%s | %s | Expires in: %s\n", peer.Encode(obj.Peer), obj.Name, humanize.Time(time.Unix(0, obj.Expire)))
|
|
}
|
|
|
|
func textFormatPrintGlobalRepoGC(obj *api.GlobalRepoGC) {
|
|
peers := make(sort.StringSlice, 0, len(obj.PeerMap))
|
|
for peer := range obj.PeerMap {
|
|
peers = append(peers, peer)
|
|
}
|
|
peers.Sort()
|
|
|
|
for _, peer := range peers {
|
|
item := obj.PeerMap[peer]
|
|
// If peer name is set, use it instead of peer ID.
|
|
if len(item.Peername) > 0 {
|
|
peer = item.Peername
|
|
}
|
|
if item.Error != "" {
|
|
fmt.Printf("%-15s | ERROR: %s\n", peer, item.Error)
|
|
} else {
|
|
fmt.Printf("%-15s\n", peer)
|
|
}
|
|
|
|
fmt.Printf(" > CIDs:\n")
|
|
for _, key := range item.Keys {
|
|
if key.Error != "" {
|
|
// key.Key will be empty
|
|
fmt.Printf(" - ERROR: %s\n", key.Error)
|
|
continue
|
|
}
|
|
|
|
fmt.Printf(" - %s\n", key.Key)
|
|
}
|
|
}
|
|
}
|
|
|
|
func textFormatPrintError(obj *api.Error) {
|
|
fmt.Printf("An error occurred:\n")
|
|
fmt.Printf(" Code: %d\n", obj.Code)
|
|
fmt.Printf(" Message: %s\n", obj.Message)
|
|
}
|
|
|
|
func trackerStatusAllString() string {
|
|
var strs []string
|
|
for _, st := range api.TrackerStatusAll() {
|
|
strs = append(strs, " - "+st.String())
|
|
}
|
|
|
|
sort.Strings(strs)
|
|
return strings.Join(strs, "\n")
|
|
}
|