From e71ca7c5ad5a311440024f944197f51069b560a0 Mon Sep 17 00:00:00 2001 From: Kejie Zhang <601172892@qq.com> Date: Mon, 17 Sep 2018 15:09:55 +0800 Subject: [PATCH 1/4] refactor ipns command option name License: MIT Signed-off-by: Kejie Zhang <601172892@qq.com> --- core/commands/name/ipns.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/core/commands/name/ipns.go b/core/commands/name/ipns.go index d187fcf61..e97c395c7 100644 --- a/core/commands/name/ipns.go +++ b/core/commands/name/ipns.go @@ -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)) From 264a9fee646c54c146c05af9d4ae22c5e504adb0 Mon Sep 17 00:00:00 2001 From: Kejie Zhang <601172892@qq.com> Date: Mon, 17 Sep 2018 16:10:18 +0800 Subject: [PATCH 2/4] add `allow-offline` to judge publish in offline mode License: MIT Signed-off-by: Kejie Zhang <601172892@qq.com> --- core/commands/name/publish.go | 43 ++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/core/commands/name/publish.go b/core/commands/name/publish.go index 92ddea685..3175b4517 100644 --- a/core/commands/name/publish.go +++ b/core/commands/name/publish.go @@ -19,6 +19,21 @@ import ( path "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path" ) +var ( + ErrAllowOffline = errors.New("cannot publish in offline mode by default,using `--allow-offline` to publish again") + 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 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. <> 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: <>.").WithDefault("self"), + cmdkit.BoolOption(allowOfflineOptionName, "Allow publish in offline mode"), + 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: <>.").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 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 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 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 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) From 9a534944402bd4d0470d22e448f870318a400aaa Mon Sep 17 00:00:00 2001 From: Kejie Zhang <601172892@qq.com> Date: Mon, 17 Sep 2018 16:32:04 +0800 Subject: [PATCH 3/4] update test about publish offline mode License: MIT Signed-off-by: Kejie Zhang <601172892@qq.com> --- core/commands/name/publish.go | 22 +++++++++++----------- test/sharness/t0100-name.sh | 32 ++++++++++++++++++++++---------- test/sharness/t0110-gateway.sh | 2 +- test/sharness/t0160-resolve.sh | 4 ++-- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/core/commands/name/publish.go b/core/commands/name/publish.go index 3175b4517..db8941b6f 100644 --- a/core/commands/name/publish.go +++ b/core/commands/name/publish.go @@ -20,18 +20,18 @@ import ( ) var ( - ErrAllowOffline = errors.New("cannot publish in offline mode by default,using `--allow-offline` to publish again") - ErrIpnsMount = errors.New("cannot manually publish while IPNS is mounted") - ErrIdentityLoad = errors.New("identity not loaded") + errAllowOffline = errors.New("cannot publish in offline mode by default,using `--allow-offline` to publish again") + errIpnsMount = errors.New("cannot manually publish while IPNS is mounted") + errIdentityLoad = errors.New("identity not loaded") ) const ( - ipfsPathOptionName = "ipfs-path" - resolveOptionName = "resolve" + ipfsPathOptionName = "ipfs-path" + resolveOptionName = "resolve" allowOfflineOptionName = "allow-offline" - lifeTimeOptionName = "lifetime" - ttlOptionName = "ttl" - keyOptionName = "key" + lifeTimeOptionName = "lifetime" + ttlOptionName = "ttl" + keyOptionName = "key" ) var PublishCmd = &cmds.Command{ @@ -97,7 +97,7 @@ Alternatively, publish an using a valid PeerID (as listed by allowOffline, _ := req.Options[allowOfflineOptionName].(bool) if !n.OnlineMode() { if !allowOffline { - res.SetError(ErrAllowOffline,cmdkit.ErrNormal) + res.SetError(errAllowOffline, cmdkit.ErrNormal) return } err := n.SetupOfflineRouting() @@ -108,14 +108,14 @@ Alternatively, publish an using a valid PeerID (as listed by } if n.Mounts.Ipns != nil && n.Mounts.Ipns.IsActive() { - res.SetError(ErrIpnsMount, cmdkit.ErrNormal) + res.SetError(errIpnsMount, cmdkit.ErrNormal) return } pstr := req.Arguments[0] if n.Identity == "" { - res.SetError(ErrIdentityLoad, cmdkit.ErrNormal) + res.SetError(errIdentityLoad, cmdkit.ErrNormal) return } diff --git a/test/sharness/t0100-name.sh b/test/sharness/t0100-name.sh index 7dbaa7f79..f0ce9f090 100755 --- a/test/sharness/t0100-name.sh +++ b/test/sharness/t0100-name.sh @@ -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=""` && 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=""` && 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 ' succeeds" ' +test_expect_failure "'ipfs name publish --allow-offline ' succeeds" ' PEERID=`ipfs id --format=""` && 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= ' succeeds" ' - ipfs name publish --key=${NEWID} "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish +test_expect_success "'ipfs name publis --allow-offline --key= ' 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=""` && + test_check_peerid "${PEERID}" && + test_expect_code 1 ipfs name publish "/ipfs/$HASH_WELCOME_DOCS" +' + +test_kill_ipfs_daemon + test_done diff --git a/test/sharness/t0110-gateway.sh b/test/sharness/t0110-gateway.sh index 7d519911b..8c5d4982f 100755 --- a/test/sharness/t0110-gateway.sh +++ b/test/sharness/t0110-gateway.sh @@ -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" diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh index d64c0eac5..dacd05d9f 100755 --- a/test/sharness/t0160-resolve.sh +++ b/test/sharness/t0160-resolve.sh @@ -19,7 +19,7 @@ test_resolve_setup_name() { test_expect_success "resolve: prepare name" ' id_hash=$(ipfs id -f="") && - 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="") && - 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 From 5676eb530b95b8db9fb292371238cab8977c0d6f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 19 Sep 2018 00:25:22 +0000 Subject: [PATCH 4/4] cmds: improve help/errors for allow-offline Better explain what's happening and why. License: MIT Signed-off-by: Steven Allen --- core/commands/name/publish.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/commands/name/publish.go b/core/commands/name/publish.go index db8941b6f..c1489baeb 100644 --- a/core/commands/name/publish.go +++ b/core/commands/name/publish.go @@ -20,7 +20,7 @@ import ( ) var ( - errAllowOffline = errors.New("cannot publish in offline mode by default,using `--allow-offline` to publish again") + 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") ) @@ -83,7 +83,7 @@ Alternatively, publish an using a valid PeerID (as listed by `Time duration that the record will be valid for. <> 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.BoolOption(allowOfflineOptionName, "Allow publish in offline mode"), + 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: <>.").WithDefault("self"), },