@cryptotaxi247 / kubo / commits / 074305690

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=