fsrepo: fix musl detection for migrations
The ldd command used for detection doesn't seem to have a --version flag on Alpine Linux. It would print the expected output, but instead of stdout, it would print it on stderr. The musl detection code would only scan stdout for mentions of "musl", and would thus *not* download the musl version of the fs-repo-migrations executable. This manifested in the well-known "fs-repo-migrations: not found" error, which you get when executing something that was linked against a different libc than the one present on the system. License: MIT Signed-off-by: Lars Gierth <larsg@systemli.org>
Lars Gierth committed
Feb 16, 2017 at 15:23 UTC
26770b7ebb8a9864bf656f9c220ea6dd064ff2ec
3 files changed
+44
-14
repo/fsrepo/migrations/migrations.go
+16
-13
@@ -243,27 +243,30 @@ func GetBinaryForVersion(distname, binnom, root, vers, out string) error {
243
return unpackArchive(distname, binnom, arcpath, out, archive)
244
}
245
246
+// osWithVariant returns the OS name with optional variant.
247
+// Currently returns either runtime.GOOS, or "linux-musl".
248
func osWithVariant() (string, error) {
249
if runtime.GOOS != "linux" {
250
return runtime.GOOS, nil
251
}
252
251
- bin, err := exec.LookPath(filepath.Base(os.Args[0]))
253
+ // ldd outputs the system's kind of libc.
254
+ // - on standard ubuntu: ldd (Ubuntu GLIBC 2.23-0ubuntu5) 2.23
255
+ // - on alpine: musl libc (x86_64)
256
+ //
257
+ // we use the combined stdout+stderr,
258
+ // because ldd --version prints differently on different OSes.
259
+ // - on standard ubuntu: stdout
260
+ // - on alpine: stderr (it probably doesn't know the --version flag)
261
+ //
262
+ // we supress non-zero exit codes (see last point about alpine).
263
+ out, err := exec.Command("sh", "-c", "ldd --version || true").CombinedOutput()
264
if err != nil {
253
- return "", fmt.Errorf("failed to resolve go-ipfs: %s", err)
265
+ return "", err
266
}
267
256
- // ldd outputs the system's kind of libc
257
- // - on standard ubuntu: ldd (Ubuntu GLIBC 2.23-0ubuntu5) 2.23
258
- // - on alpine: musl libc (x86_64)
259
- cmd := exec.Command("ldd --version", bin)
260
- buf := new(bytes.Buffer)
261
- cmd.Stdout = buf
262
- // we throw away the error, this code path must not fail because of
263
- // a silly issue such as missing/broken ldd. we'll assume glibc in that case.
264
- _ = cmd.Run()
265
-
266
- scan := bufio.NewScanner(buf)
268
+ // now just see if we can find "musl" somewhere in the output
269
+ scan := bufio.NewScanner(bytes.NewBuffer(out))
270
for scan.Scan() {
271
if strings.Contains(scan.Text(), "musl") {
272
return "linux-musl", nil
test/sharness/lib/test-lib.sh
+1
-1
@@ -147,7 +147,7 @@ test_init_ipfs() {
147
test_config_set Mounts.IPFS "$(pwd)/ipfs" &&
148
test_config_set Mounts.IPNS "$(pwd)/ipns" &&
149
test_config_set Addresses.API "/ip4/127.0.0.1/tcp/0" &&
150
- test_config_set Addresses.Gateway "/ip4/127.0.0.1/tcp/0" &&
150
+ test_config_set Addresses.Gateway "/ip4/0.0.0.0/tcp/0" &&
151
test_config_set --json Addresses.Swarm "[
152
\"/ip4/0.0.0.0/tcp/0\"
153
]" &&
test/sharness/t0066-migration.sh
+27
@@ -49,4 +49,31 @@ test_expect_success "output looks good" '
49
grep "Please get fs-repo-migrations from https://dist.ipfs.io" daemon_out > /dev/null
50
'
51
52
+test_launch_ipfs_daemon
53
+
54
+test_expect_success "build fake dist.ipfs.io" '
55
+ mkdir -p fakedist/fs-repo-migrations/v1.0.0/
56
+ echo "v1.0.0" > fakedist/fs-repo-migrations/versions
57
+
58
+ echo "#!/bin/sh" > fakedist/linux
59
+ echo "echo linux $@" >> fakedist/linux
60
+ tar -czf fakedist/fs-repo-migrations/fs-repo-migrations_v1.0.0_linux-amd64.tar.gz fakedist/linux
61
+
62
+ echo "#!/bin/sh" > fakedist/linux-musl
63
+ echo "echo linux-musl $@" >> fakedist/linux-musl
64
+ tar -czf fakedist/fs-repo-migrations/fs-repo-migrations_v1.0.0_linux-musl-amd64.tar.gz fakedist/linux-musl
65
+
66
+ ipfs add -q -r fakedist/ > fakedisthash
67
+'
68
+
69
+test_expect_success "detect musl" '
70
+ IPFS_DIST_PATH="http://172.17.0.1:$GWAY_PORT" echo $IPFS_DIST_PATH
71
+'
72
+
73
+# make fakedist with executables that just echo "I'm $GOOS-$variant with $ARGV"
74
+# ipfs add -r fakedist
75
+# find out IPFS_DIST_PATH
76
+# run daemon --migrate end-to-end
77
+# check for correct output
78
+
79
test_done