fix: ignore stale APIs
fixes #5784
Steven Allen committed
Jun 29, 2019 at 10:32 UTC
074305690a36482ca6f32a18c29c241f542a2421
3 files changed
+85
-135
cmd/ipfs/main.go
+82
-131
@@ -21,7 +21,6 @@ import (
21
repo "github.com/ipfs/go-ipfs/repo"
22
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
23
24
- osh "github.com/Kubuxu/go-os-helper"
24
"github.com/ipfs/go-ipfs-cmds"
25
"github.com/ipfs/go-ipfs-cmds/cli"
26
"github.com/ipfs/go-ipfs-cmds/http"
@@ -195,21 +194,90 @@ func checkDebug(req *cmds.Request) {
194
}
195
}
196
197
+func apiAddrOption(req *cmds.Request) (ma.Multiaddr, error) {
198
+ apiAddrStr, apiSpecified := req.Options[corecmds.ApiOption].(string)
199
+ if !apiSpecified {
200
+ return nil, nil
201
+ }
202
+ return ma.NewMultiaddr(apiAddrStr)
203
+}
204
+
205
func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) {
206
+ exe := cmds.NewExecutor(req.Root)
207
+ cctx := env.(*oldcmds.Context)
208
details := commandDetails(req.Path)
200
- client, err := commandShouldRunOnDaemon(*details, req, env.(*oldcmds.Context))
209
+
210
+ // Check if the command is disabled.
211
+ if details.cannotRunOnClient && details.cannotRunOnDaemon {
212
+ return nil, fmt.Errorf("command disabled: %v", req.Path)
213
+ }
214
+
215
+ // Can we just run this locally?
216
+ if !details.cannotRunOnClient && details.doesNotUseRepo {
217
+ return exe, nil
218
+ }
219
+
220
+ // Get the API option from the commandline.
221
+ apiAddr, err := apiAddrOption(req)
222
if err != nil {
223
return nil, err
224
}
225
205
- var exctr cmds.Executor
206
- if client != nil && !req.Command.External {
207
- exctr = client.(cmds.Executor)
208
- } else {
209
- exctr = cmds.NewExecutor(req.Root)
226
+ // Force the daemon when the API flag is passed (unless we're trying to
227
+ // _run_ the daemon).
228
+ daemonForced := apiAddr != nil && req.Command != daemonCmd
229
+
230
+ // Run this on the client if required.
231
+ if details.cannotRunOnDaemon || req.Command.External {
232
+ if daemonForced {
233
+ // User requested that the command be run on the daemon but we can't.
234
+ // NOTE: We drop this check for the `ipfs daemon` command.
235
+ return nil, errors.New("api flag specified but command cannot be run on the daemon")
236
+ }
237
+ return exe, nil
238
+ }
239
+
240
+ // Finally, look in the repo for an API file.
241
+ if apiAddr == nil {
242
+ var err error
243
+ apiAddr, err = fsrepo.APIAddr(cctx.ConfigRoot)
244
+ switch err {
245
+ case nil, repo.ErrApiNotRunning:
246
+ default:
247
+ return nil, err
248
+ }
249
}
250
212
- return exctr, nil
251
+ // Still no api specified? Run it on the client or fail.
252
+ if apiAddr == nil {
253
+ if details.cannotRunOnClient {
254
+ return nil, fmt.Errorf("command must be run on the daemon: %v", req.Path)
255
+ }
256
+ return exe, nil
257
+ }
258
+
259
+ // Resolve the API addr.
260
+ apiAddr, err = resolveAddr(req.Context, apiAddr)
261
+ if err != nil {
262
+ return nil, err
263
+ }
264
+ _, host, err := manet.DialArgs(apiAddr)
265
+ if err != nil {
266
+ return nil, err
267
+ }
268
+
269
+ // Construct the executor.
270
+ opts := []http.ClientOpt{
271
+ http.ClientWithAPIPrefix(corehttp.APIPath),
272
+ }
273
+
274
+ // Fallback on a local executor if we (a) have a repo and (b) aren't
275
+ // forcing a daemon.
276
+ if !daemonForced && fsrepo.IsInitialized(cctx.ConfigRoot) {
277
+ opts = append(opts, http.ClientWithFallback(exe))
278
+ }
279
+
280
+ return http.NewClient(host, opts...), nil
281
}
282
283
func checkPermissions(path string) (bool, error) {
@@ -227,7 +295,11 @@ func checkPermissions(path string) (bool, error) {
295
}
296
297
// commandDetails returns a command's details for the command given by |path|.
230
-func commandDetails(path []string) *cmdDetails {
298
+func commandDetails(path []string) cmdDetails {
299
+ if len(path) == 0 {
300
+ // special case root command
301
+ return cmdDetails{doesNotUseRepo: true}
302
+ }
303
var details cmdDetails
304
// find the last command in path that has a cmdDetailsMap entry
305
for i := range path {
@@ -235,67 +307,7 @@ func commandDetails(path []string) *cmdDetails {
307
details = cmdDetails
308
}
309
}
238
- return &details
239
-}
240
-
241
-// commandShouldRunOnDaemon determines, from command details, whether a
242
-// command ought to be executed on an ipfs daemon.
243
-//
244
-// It returns a client if the command should be executed on a daemon and nil if
245
-// it should be executed on a client. It returns an error if the command must
246
-// NOT be executed on either.
247
-func commandShouldRunOnDaemon(details cmdDetails, req *cmds.Request, cctx *oldcmds.Context) (http.Client, error) {
248
- path := req.Path
249
- // root command.
250
- if len(path) < 1 {
251
- return nil, nil
252
- }
253
-
254
- if details.cannotRunOnClient && details.cannotRunOnDaemon {
255
- return nil, fmt.Errorf("command disabled: %s", path[0])
256
- }
257
-
258
- if details.doesNotUseRepo && details.canRunOnClient() {
259
- return nil, nil
260
- }
261
-
262
- // at this point need to know whether api is running. we defer
263
- // to this point so that we don't check unnecessarily
264
-
265
- // did user specify an api to use for this command?
266
- apiAddrStr, _ := req.Options[corecmds.ApiOption].(string)
267
-
268
- client, err := getAPIClient(req.Context, cctx.ConfigRoot, apiAddrStr)
269
- if err == repo.ErrApiNotRunning {
270
- if apiAddrStr != "" && req.Command != daemonCmd {
271
- // if user SPECIFIED an api, and this cmd is not daemon
272
- // we MUST use it. so error out.
273
- return nil, err
274
- }
275
-
276
- // ok for api not to be running
277
- } else if err != nil { // some other api error
278
- return nil, err
279
- }
280
-
281
- if client != nil {
282
- if details.cannotRunOnDaemon {
283
- // check if daemon locked. legacy error text, for now.
284
- log.Debugf("Command cannot run on daemon. Checking if daemon is locked")
285
- if daemonLocked, _ := fsrepo.LockedByOtherProcess(cctx.ConfigRoot); daemonLocked {
286
- return nil, cmds.ClientError("ipfs daemon is running. please stop it to run this command")
287
- }
288
- return nil, nil
289
- }
290
-
291
- return client, nil
292
- }
293
-
294
- if details.cannotRunOnClient {
295
- return nil, cmds.ClientError("must run on the ipfs daemon")
296
- }
297
-
298
- return nil, nil
310
+ return details
311
}
312
313
func getRepoPath(req *cmds.Request) (string, error) {
@@ -366,67 +378,6 @@ func profileIfEnabled() (func(), error) {
378
return func() {}, nil
379
}
380
369
-var apiFileErrorFmt string = `Failed to parse '%[1]s/api' file.
370
- error: %[2]s
371
-If you're sure go-ipfs isn't running, you can just delete it.
372
-`
373
-var checkIPFSUnixFmt = "Otherwise check:\n\tps aux | grep ipfs"
374
-var checkIPFSWinFmt = "Otherwise check:\n\ttasklist | findstr ipfs"
375
-
376
-// getAPIClient checks the repo, and the given options, checking for
377
-// a running API service. if there is one, it returns a client.
378
-// otherwise, it returns errApiNotRunning, or another error.
379
-func getAPIClient(ctx context.Context, repoPath, apiAddrStr string) (http.Client, error) {
380
- var apiErrorFmt string
381
- switch {
382
- case osh.IsUnix():
383
- apiErrorFmt = apiFileErrorFmt + checkIPFSUnixFmt
384
- case osh.IsWindows():
385
- apiErrorFmt = apiFileErrorFmt + checkIPFSWinFmt
386
- default:
387
- apiErrorFmt = apiFileErrorFmt
388
- }
389
-
390
- var addr ma.Multiaddr
391
- var err error
392
- if len(apiAddrStr) != 0 {
393
- addr, err = ma.NewMultiaddr(apiAddrStr)
394
- if err != nil {
395
- return nil, err
396
- }
397
- if len(addr.Protocols()) == 0 {
398
- return nil, fmt.Errorf("multiaddr doesn't provide any protocols")
399
- }
400
- } else {
401
- addr, err = fsrepo.APIAddr(repoPath)
402
- if err == repo.ErrApiNotRunning {
403
- return nil, err
404
- }
405
-
406
- if err != nil {
407
- return nil, fmt.Errorf(apiErrorFmt, repoPath, err.Error())
408
- }
409
- }
410
- if len(addr.Protocols()) == 0 {
411
- return nil, fmt.Errorf(apiErrorFmt, repoPath, "multiaddr doesn't provide any protocols")
412
- }
413
- return apiClientForAddr(ctx, addr)
414
-}
415
-
416
-func apiClientForAddr(ctx context.Context, addr ma.Multiaddr) (http.Client, error) {
417
- addr, err := resolveAddr(ctx, addr)
418
- if err != nil {
419
- return nil, err
420
- }
421
-
422
- _, host, err := manet.DialArgs(addr)
423
- if err != nil {
424
- return nil, err
425
- }
426
-
427
- return http.NewClient(host, http.ClientWithAPIPrefix(corehttp.APIPath)), nil
428
-}
429
-
381
func resolveAddr(ctx context.Context, addr ma.Multiaddr) (ma.Multiaddr, error) {
382
ctx, cancelFunc := context.WithTimeout(ctx, 10*time.Second)
383
defer cancelFunc()
go.mod
+1
-2
@@ -2,7 +2,6 @@ module github.com/ipfs/go-ipfs
2
3
require (
4
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669
5
- github.com/Kubuxu/go-os-helper v0.0.1
5
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd
6
github.com/blang/semver v3.5.1+incompatible
7
github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d
@@ -32,7 +31,7 @@ require (
31
github.com/ipfs/go-ipfs-blockstore v0.0.1
32
github.com/ipfs/go-ipfs-blocksutil v0.0.1
33
github.com/ipfs/go-ipfs-chunker v0.0.1
35
- github.com/ipfs/go-ipfs-cmds v0.0.10
34
+ github.com/ipfs/go-ipfs-cmds v0.1.0
35
github.com/ipfs/go-ipfs-config v0.0.6
36
github.com/ipfs/go-ipfs-ds-help v0.0.1
37
github.com/ipfs/go-ipfs-exchange-interface v0.0.1
go.sum
+2
-2
@@ -247,8 +247,8 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IW
247
github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk=
248
github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw=
249
github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw=
250
-github.com/ipfs/go-ipfs-cmds v0.0.10 h1:4kA3E94HbDrLb4RZTkX3yXyUjKv50RfPz0Pv9xkP2cA=
251
-github.com/ipfs/go-ipfs-cmds v0.0.10/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8=
250
+github.com/ipfs/go-ipfs-cmds v0.1.0 h1:0CEde9EcxByej8+L6d1PST57J4ambRPyCTjLG5Ymou8=
251
+github.com/ipfs/go-ipfs-cmds v0.1.0/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8=
252
github.com/ipfs/go-ipfs-config v0.0.5 h1:D9ek19anOzm8iYPvezeeamSg5mzwqKPb2jyAyJZT/4A=
253
github.com/ipfs/go-ipfs-config v0.0.5/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM=
254
github.com/ipfs/go-ipfs-config v0.0.6 h1:jzK9Tl8S0oWBir3F5ObtGgnHRPdqQ0MYiCmwXtV3Ps4=