Skip to content

Commit 3b6f577

Browse files
authored
Expose additional migration APIs (ipfs#8153)
* Expose additional migration APIs Expose migration APIs for reading migration config and creating migration fetchers. This allows implementation of commands and external applications that want to retrieve migrations according to the Migration portion of the IPFS config. This change also moves some functionality that is specific to fetching migrations via IPFS into the `ipfsfetcher` package.
1 parent cab67f6 commit 3b6f577

File tree

10 files changed

+526
-511
lines changed

10 files changed

+526
-511
lines changed

cmd/ipfs/migration.go renamed to cmd/ipfs/add_migrations.go

+1-138
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@ package main
22

33
import (
44
"context"
5-
"encoding/json"
65
"errors"
76
"fmt"
87
"io"
98
"io/ioutil"
10-
"net/url"
119
"os"
1210
"path/filepath"
13-
"strings"
1411

15-
config "github.com/ipfs/go-ipfs-config"
1612
"github.com/ipfs/go-ipfs-files"
1713
"github.com/ipfs/go-ipfs/core"
1814
"github.com/ipfs/go-ipfs/core/coreapi"
@@ -24,140 +20,7 @@ import (
2420
"github.com/libp2p/go-libp2p-core/peer"
2521
)
2622

27-
// readMigrationConfig reads the migration config out of the config, avoiding
28-
// reading anything other than the migration section. That way, we're free to
29-
// make arbitrary changes to all _other_ sections in migrations.
30-
func readMigrationConfig(repoRoot string) (*config.Migration, error) {
31-
var cfg struct {
32-
Migration config.Migration
33-
}
34-
35-
cfgPath, err := config.Filename(repoRoot)
36-
if err != nil {
37-
return nil, err
38-
}
39-
40-
cfgFile, err := os.Open(cfgPath)
41-
if err != nil {
42-
return nil, err
43-
}
44-
defer cfgFile.Close()
45-
46-
err = json.NewDecoder(cfgFile).Decode(&cfg)
47-
if err != nil {
48-
return nil, err
49-
}
50-
51-
switch cfg.Migration.Keep {
52-
case "":
53-
cfg.Migration.Keep = config.DefaultMigrationKeep
54-
case "discard", "cache", "keep":
55-
default:
56-
return nil, errors.New("unknown config value, Migrations.Keep must be 'cache', 'pin', or 'discard'")
57-
}
58-
59-
if len(cfg.Migration.DownloadSources) == 0 {
60-
cfg.Migration.DownloadSources = config.DefaultMigrationDownloadSources
61-
}
62-
63-
return &cfg.Migration, nil
64-
}
65-
66-
func readIpfsConfig(repoRoot *string) (bootstrap []string, peers []peer.AddrInfo) {
67-
if repoRoot == nil {
68-
return
69-
}
70-
71-
cfgPath, err := config.Filename(*repoRoot)
72-
if err != nil {
73-
fmt.Fprintln(os.Stderr, err)
74-
return
75-
}
76-
77-
cfgFile, err := os.Open(cfgPath)
78-
if err != nil {
79-
fmt.Fprintln(os.Stderr, err)
80-
return
81-
}
82-
defer cfgFile.Close()
83-
84-
// Attempt to read bootstrap addresses
85-
var bootstrapCfg struct {
86-
Bootstrap []string
87-
}
88-
err = json.NewDecoder(cfgFile).Decode(&bootstrapCfg)
89-
if err != nil {
90-
fmt.Fprintln(os.Stderr, "cannot read bootstrap peers from config")
91-
} else {
92-
bootstrap = bootstrapCfg.Bootstrap
93-
}
94-
95-
if _, err = cfgFile.Seek(0, 0); err != nil {
96-
fmt.Fprintln(os.Stderr, err)
97-
}
98-
99-
// Attempt to read peers
100-
var peeringCfg struct {
101-
Peering config.Peering
102-
}
103-
err = json.NewDecoder(cfgFile).Decode(&peeringCfg)
104-
if err != nil {
105-
fmt.Fprintln(os.Stderr, "cannot read peering from config")
106-
} else {
107-
peers = peeringCfg.Peering.Peers
108-
}
109-
110-
return
111-
}
112-
113-
// getMigrationFetcher creates one or more fetchers according to
114-
// config.Migration.DownloadSources. If an IpfsFetcher is required, then
115-
// bootstrap and peer information in read from the config file in repoRoot,
116-
// unless repoRoot is nil.
117-
func getMigrationFetcher(cfg *config.Migration, repoRoot *string) (migrations.Fetcher, error) {
118-
const httpUserAgent = "go-ipfs"
119-
120-
// Fetch migrations from current distribution, or location from environ
121-
fetchDistPath := migrations.GetDistPathEnv(migrations.CurrentIpfsDist)
122-
123-
var fetchers []migrations.Fetcher
124-
for _, src := range cfg.DownloadSources {
125-
src := strings.TrimSpace(src)
126-
switch src {
127-
case "IPFS", "ipfs":
128-
bootstrap, peers := readIpfsConfig(repoRoot)
129-
fetchers = append(fetchers, ipfsfetcher.NewIpfsFetcher(fetchDistPath, 0, bootstrap, peers))
130-
case "HTTPS", "https", "HTTP", "http":
131-
fetchers = append(fetchers, migrations.NewHttpFetcher(fetchDistPath, "", httpUserAgent, 0))
132-
default:
133-
u, err := url.Parse(src)
134-
if err != nil {
135-
return nil, fmt.Errorf("bad gateway address: %s", err)
136-
}
137-
switch u.Scheme {
138-
case "":
139-
u.Scheme = "https"
140-
case "https", "http":
141-
default:
142-
return nil, errors.New("bad gateway address: url scheme must be http or https")
143-
}
144-
fetchers = append(fetchers, migrations.NewHttpFetcher(fetchDistPath, u.String(), httpUserAgent, 0))
145-
case "":
146-
// Ignore empty string
147-
}
148-
}
149-
if len(fetchers) == 0 {
150-
return nil, errors.New("no sources specified")
151-
}
152-
153-
if len(fetchers) == 1 {
154-
return fetchers[0], nil
155-
}
156-
157-
// Wrap fetchers in a MultiFetcher to try them in order
158-
return migrations.NewMultiFetcher(fetchers...), nil
159-
}
160-
23+
// addMigrations adds any migration downloaded by the fetcher to the IPFS node
16124
func addMigrations(ctx context.Context, node *core.IpfsNode, fetcher migrations.Fetcher, pin bool) error {
16225
var fetchers []migrations.Fetcher
16326
if mf, ok := fetcher.(*migrations.MultiFetcher); ok {

cmd/ipfs/daemon.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
nodeMount "github.com/ipfs/go-ipfs/fuse/node"
3131
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
3232
"github.com/ipfs/go-ipfs/repo/fsrepo/migrations"
33+
"github.com/ipfs/go-ipfs/repo/fsrepo/migrations/ipfsfetcher"
3334
sockets "github.com/libp2p/go-socket-activation"
3435

3536
cmds "github.com/ipfs/go-ipfs-cmds"
@@ -294,12 +295,26 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
294295
return fmt.Errorf("fs-repo requires migration")
295296
}
296297

297-
migrationCfg, err := readMigrationConfig(cctx.ConfigRoot)
298+
// Read Migration section of IPFS config
299+
migrationCfg, err := migrations.ReadMigrationConfig(cctx.ConfigRoot)
298300
if err != nil {
299301
return err
300302
}
301303

302-
fetcher, err = getMigrationFetcher(migrationCfg, &cctx.ConfigRoot)
304+
// Define function to create IPFS fetcher. Do not supply an
305+
// already-constructed IPFS fetcher, because this may be expensive and
306+
// not needed according to migration config. Instead, supply a function
307+
// to construct the particular IPFS fetcher implementation used here,
308+
// which is called only if an IPFS fetcher is needed.
309+
newIpfsFetcher := func(distPath string) migrations.Fetcher {
310+
return ipfsfetcher.NewIpfsFetcher(distPath, 0, &cctx.ConfigRoot)
311+
}
312+
313+
// Fetch migrations from current distribution, or location from environ
314+
fetchDistPath := migrations.GetDistPathEnv(migrations.CurrentIpfsDist)
315+
316+
// Create fetchers according to migrationCfg.DownloadSources
317+
fetcher, err = migrations.GetMigrationFetcher(migrationCfg.DownloadSources, fetchDistPath, newIpfsFetcher)
303318
if err != nil {
304319
return err
305320
}

0 commit comments

Comments
 (0)