kubo/core/commands/id.go
Brian Tiger Chow 3bdb36614e fix(cmd/id) determine offline-ness with !node.OnlineMode()
It's better to have one mechanism for determining whether we're offline
and to improve the SnR of this mechanism over time. We presently have
too many arbitrary heuristics for determining whether we're running in
offline mode. TRTTD is to use polymorphism to eliminate these
conditional checks. (instantiate the node with offline versions of
routing, network, etc.) It'll clean up the core constructor, make it
easier to create ephemeral nodes, and eliminate a class of errors.

@whyrusleeping @jbenet

License: MIT
Signed-off-by: Brian Tiger Chow <brian@perfmode.com>
2014-12-05 20:56:26 -08:00

114 lines
2.6 KiB
Go

package commands
import (
"encoding/base64"
"encoding/json"
"errors"
"time"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
cmds "github.com/jbenet/go-ipfs/commands"
"github.com/jbenet/go-ipfs/peer"
kb "github.com/jbenet/go-ipfs/routing/kbucket"
u "github.com/jbenet/go-ipfs/util"
)
const offlineIdErrorMessage = `ID command fails when run without daemon, we are working to fix this.
In the meantime, please run the daemon if you want to use 'ipfs id':
ipfs daemon &
ipfs id QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
`
type IdOutput struct {
ID string
PublicKey string
Addresses []string
AgentVersion string
ProtocolVersion string
}
var IDCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Show IPFS Node ID info",
ShortDescription: `
Prints out information about the specified peer,
if no peer is specified, prints out local peers info.
`,
},
Arguments: []cmds.Argument{
cmds.StringArg("peerid", false, false, "peer.ID of node to look up"),
},
Run: func(req cmds.Request) (interface{}, error) {
node, err := req.Context().GetNode()
if err != nil {
return nil, err
}
if len(req.Arguments()) == 0 {
return printPeer(node.Identity)
}
pid := req.Arguments()[0]
id := peer.ID(b58.Decode(pid))
if len(id) == 0 {
return nil, cmds.ClientError("Invalid peer id")
}
ctx, _ := context.WithTimeout(context.TODO(), time.Second*5)
// TODO handle offline mode with polymorphism instead of conditionals
if !node.OnlineMode() {
return nil, errors.New(offlineIdErrorMessage)
}
p, err := node.Routing.FindPeer(ctx, id)
if err == kb.ErrLookupFailure {
return nil, errors.New(offlineIdErrorMessage)
}
if err != nil {
return nil, err
}
return printPeer(p)
},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) ([]byte, error) {
val, ok := res.Output().(*IdOutput)
if !ok {
return nil, u.ErrCast()
}
return json.MarshalIndent(val, "", "\t")
},
},
Type: &IdOutput{},
}
func printPeer(p peer.Peer) (interface{}, error) {
if p == nil {
return nil, errors.New("Attempted to print nil peer!")
}
info := new(IdOutput)
info.ID = p.ID().String()
if p.PubKey() != nil {
pkb, err := p.PubKey().Bytes()
if err != nil {
return nil, err
}
info.PublicKey = base64.StdEncoding.EncodeToString(pkb)
}
for _, a := range p.Addresses() {
info.Addresses = append(info.Addresses, a.String())
}
agent, protocol := p.GetVersions()
info.AgentVersion = agent
info.ProtocolVersion = protocol
return info, nil
}