Merge pull request #5477 from kjzz/fix/publish

error when publishing ipns records without a running daemon
This commit is contained in:
Steven Allen 2018-09-19 02:19:31 +00:00 committed by GitHub
commit e633eccee4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 31 deletions

View File

@ -25,6 +25,13 @@ type ResolvedPath struct {
Path path.Path
}
const (
recursiveOptionName = "recursive"
nocacheOptionName = "nocache"
dhtRecordCountOptionName = "dht-record-count"
dhtTimeoutOptionName = "dht-timeout"
)
var IpnsCmd = &cmds.Command{
Helptext: cmdkit.HelpText{
Tagline: "Resolve IPNS names.",
@ -67,10 +74,10 @@ Resolve the value of a dnslink:
cmdkit.StringArg("name", false, false, "The IPNS name to resolve. Defaults to your node's peerID."),
},
Options: []cmdkit.Option{
cmdkit.BoolOption("recursive", "r", "Resolve until the result is not an IPNS name."),
cmdkit.BoolOption("nocache", "n", "Do not use cached entries."),
cmdkit.UintOption("dht-record-count", "dhtrc", "Number of records to request for DHT resolution."),
cmdkit.StringOption("dht-timeout", "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."),
cmdkit.BoolOption(recursiveOptionName, "r", "Resolve until the result is not an IPNS name."),
cmdkit.BoolOption(nocacheOptionName, "n", "Do not use cached entries."),
cmdkit.UintOption(dhtRecordCountOptionName, "dhtrc", "Number of records to request for DHT resolution."),
cmdkit.StringOption(dhtTimeoutOptionName, "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
n, err := cmdenv.GetNode(env)
@ -119,9 +126,10 @@ Resolve the value of a dnslink:
name = req.Arguments[0]
}
recursive, _ := req.Options["recursive"].(bool)
rc, rcok := req.Options["dht-record-count"].(int)
dhtt, dhttok := req.Options["dht-timeout"].(string)
recursive, _ := req.Options[recursiveOptionName].(bool)
rc, rcok := req.Options[dhtRecordCountOptionName].(int)
dhtt, dhttok := req.Options[dhtTimeoutOptionName].(string)
var ropts []nsopts.ResolveOpt
if !recursive {
ropts = append(ropts, nsopts.Depth(1))

View File

@ -19,6 +19,21 @@ import (
path "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path"
)
var (
errAllowOffline = errors.New("can't publish while offline: pass `--allow-offline` to override")
errIpnsMount = errors.New("cannot manually publish while IPNS is mounted")
errIdentityLoad = errors.New("identity not loaded")
)
const (
ipfsPathOptionName = "ipfs-path"
resolveOptionName = "resolve"
allowOfflineOptionName = "allow-offline"
lifeTimeOptionName = "lifetime"
ttlOptionName = "ttl"
keyOptionName = "key"
)
var PublishCmd = &cmds.Command{
Helptext: cmdkit.HelpText{
Tagline: "Publish IPNS names.",
@ -60,16 +75,17 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
},
Arguments: []cmdkit.Argument{
cmdkit.StringArg("ipfs-path", true, false, "ipfs path of the object to be published.").EnableStdin(),
cmdkit.StringArg(ipfsPathOptionName, true, false, "ipfs path of the object to be published.").EnableStdin(),
},
Options: []cmdkit.Option{
cmdkit.BoolOption("resolve", "Resolve given path before publishing.").WithDefault(true),
cmdkit.StringOption("lifetime", "t",
cmdkit.BoolOption(resolveOptionName, "Resolve given path before publishing.").WithDefault(true),
cmdkit.StringOption(lifeTimeOptionName, "t",
`Time duration that the record will be valid for. <<default>>
This accepts durations such as "300s", "1.5h" or "2h45m". Valid time units are
"ns", "us" (or "µs"), "ms", "s", "m", "h".`).WithDefault("24h"),
cmdkit.StringOption("ttl", "Time duration this record should be cached for (caution: experimental)."),
cmdkit.StringOption("key", "k", "Name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'. Default: <<default>>.").WithDefault("self"),
cmdkit.BoolOption(allowOfflineOptionName, "When offline, save the IPNS record to the the local datastore without broadcasting to the network instead of simply failing."),
cmdkit.StringOption(ttlOptionName, "Time duration this record should be cached for (caution: experimental)."),
cmdkit.StringOption(keyOptionName, "k", "Name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'. Default: <<default>>.").WithDefault("self"),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
n, err := cmdenv.GetNode(env)
@ -78,7 +94,12 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
return
}
allowOffline, _ := req.Options[allowOfflineOptionName].(bool)
if !n.OnlineMode() {
if !allowOffline {
res.SetError(errAllowOffline, cmdkit.ErrNormal)
return
}
err := n.SetupOfflineRouting()
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
@ -87,22 +108,22 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
}
if n.Mounts.Ipns != nil && n.Mounts.Ipns.IsActive() {
res.SetError(errors.New("cannot manually publish while IPNS is mounted"), cmdkit.ErrNormal)
res.SetError(errIpnsMount, cmdkit.ErrNormal)
return
}
pstr := req.Arguments[0]
if n.Identity == "" {
res.SetError(errors.New("identity not loaded"), cmdkit.ErrNormal)
res.SetError(errIdentityLoad, cmdkit.ErrNormal)
return
}
popts := new(publishOpts)
popts.verifyExists, _ = req.Options["resolve"].(bool)
popts.verifyExists, _ = req.Options[resolveOptionName].(bool)
validtime, _ := req.Options["lifetime"].(string)
validtime, _ := req.Options[lifeTimeOptionName].(string)
d, err := time.ParseDuration(validtime)
if err != nil {
res.SetError(fmt.Errorf("error parsing lifetime option: %s", err), cmdkit.ErrNormal)
@ -112,7 +133,7 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
popts.pubValidTime = d
ctx := req.Context
if ttl, found := req.Options["ttl"].(string); found {
if ttl, found := req.Options[ttlOptionName].(string); found {
d, err := time.ParseDuration(ttl)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
@ -122,7 +143,7 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
ctx = context.WithValue(ctx, "ipns-publish-ttl", d)
}
kname, _ := req.Options["key"].(string)
kname, _ := req.Options[keyOptionName].(string)
k, err := keylookup(n, kname)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)

View File

@ -12,10 +12,11 @@ test_init_ipfs
# test publishing a hash
test_expect_success "'ipfs name publish' succeeds" '
test_expect_success "'ipfs name publish --allow-offline' succeeds" '
PEERID=`ipfs id --format="<id>"` &&
test_check_peerid "${PEERID}" &&
ipfs name publish "/ipfs/$HASH_WELCOME_DOCS" >publish_out
ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS" >publish_out
'
test_expect_success "publish output looks good" '
@ -34,10 +35,10 @@ test_expect_success "resolve output looks good" '
# now test with a path
test_expect_success "'ipfs name publish' succeeds" '
test_expect_success "'ipfs name publish --allow-offline' succeeds" '
PEERID=`ipfs id --format="<id>"` &&
test_check_peerid "${PEERID}" &&
ipfs name publish "/ipfs/$HASH_WELCOME_DOCS/help" >publish_out
ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS/help" >publish_out
'
test_expect_success "publish a path looks good" '
@ -62,11 +63,11 @@ test_expect_success "ipfs cat on published content succeeds" '
# publish with an explicit node ID
test_expect_failure "'ipfs name publish <local-id> <hash>' succeeds" '
test_expect_failure "'ipfs name publish --allow-offline <local-id> <hash>' succeeds" '
PEERID=`ipfs id --format="<id>"` &&
test_check_peerid "${PEERID}" &&
echo ipfs name publish "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" &&
ipfs name publish "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
echo ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" &&
ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
'
test_expect_failure "publish with our explicit node ID looks good" '
@ -81,8 +82,8 @@ test_expect_success "generate and verify a new key" '
test_check_peerid "${NEWID}"
'
test_expect_success "'ipfs name publish --key=<peer-id> <hash>' succeeds" '
ipfs name publish --key=${NEWID} "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
test_expect_success "'ipfs name publis --allow-offline --key=<peer-id> <hash>' succeeds" '
ipfs name publish --allow-offline --key=${NEWID} "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
'
test_expect_success "publish an explicit node ID as key name looks good" '
@ -94,7 +95,7 @@ test_expect_success "publish an explicit node ID as key name looks good" '
# test publishing nothing
test_expect_success "'ipfs name publish' fails" '
printf '' | test_expect_code 1 ipfs name publish >publish_out 2>&1
printf '' | test_expect_code 1 ipfs name publish --allow-offline >publish_out 2>&1
'
test_expect_success "publish output has the correct error" '
@ -115,4 +116,15 @@ test_expect_success "empty request to name publish doesn't panic and returns err
test_kill_ipfs_daemon
# Test daemon in offline mode
test_launch_ipfs_daemon --offline
test_expect_success "'ipfs name publish' fails offline mode" '
PEERID=`ipfs id --format="<id>"` &&
test_check_peerid "${PEERID}" &&
test_expect_code 1 ipfs name publish "/ipfs/$HASH_WELCOME_DOCS"
'
test_kill_ipfs_daemon
test_done

View File

@ -62,7 +62,7 @@ test_expect_success "GET IPFS non existent file returns code expected (404)" '
'
test_expect_failure "GET IPNS path succeeds" '
ipfs name publish "$HASH" &&
ipfs name publish --allow-offline "$HASH" &&
PEERID=$(ipfs config Identity.PeerID) &&
test_check_peerid "$PEERID" &&
curl -sfo actual "http://127.0.0.1:$port/ipns/$PEERID"

View File

@ -19,7 +19,7 @@ test_resolve_setup_name() {
test_expect_success "resolve: prepare name" '
id_hash=$(ipfs id -f="<id>") &&
ipfs name publish "$ref" &&
ipfs name publish --allow-offline "$ref" &&
printf "$ref\n" >expected_nameval &&
ipfs name resolve >actual_nameval &&
test_cmp expected_nameval actual_nameval
@ -31,7 +31,7 @@ test_resolve_setup_name_fail() {
test_expect_failure "resolve: prepare name" '
id_hash=$(ipfs id -f="<id>") &&
ipfs name publish "$ref" &&
ipfs name publish --allow-offline "$ref" &&
printf "$ref" >expected_nameval &&
ipfs name resolve >actual_nameval &&
test_cmp expected_nameval actual_nameval