Skip to content

Commit

Permalink
Merge pull request #5477 from kjzz/fix/publish
Browse files Browse the repository at this point in the history
error when publishing ipns records without a running daemon
  • Loading branch information
Stebalien authored Sep 19, 2018
2 parents 87250b1 + 5676eb5 commit e633ecc
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 31 deletions.
22 changes: 15 additions & 7 deletions core/commands/name/ipns.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand Down
43 changes: 32 additions & 11 deletions core/commands/name/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
32 changes: 22 additions & 10 deletions test/sharness/t0100-name.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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" '
Expand All @@ -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" '
Expand All @@ -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" '
Expand All @@ -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" '
Expand All @@ -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" '
Expand All @@ -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
2 changes: 1 addition & 1 deletion test/sharness/t0110-gateway.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions test/sharness/t0160-resolve.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit e633ecc

Please sign in to comment.