Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix IPFS container start routine #3181

Merged
merged 1 commit into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions cmd/nerdctl/ipfs_compose_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ import (

"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/testregistry"
"gotest.tools/v3/assert"
)

func TestIPFSComposeUp(t *testing.T) {
testutil.DockerIncompatible(t)
base := testutil.NewBase(t)
ipfsaddr, done := runIPFSDaemonContainer(t, base)
defer done()

iReg := testregistry.NewIPFSRegistry(base, nil, 0, nil, nil)
t.Cleanup(func() {
iReg.Cleanup(nil)
})
ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/%d", iReg.IP, iReg.Port)

tests := []struct {
name string
snapshotter string
Expand Down
35 changes: 7 additions & 28 deletions cmd/nerdctl/ipfs_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ package main

import (
"fmt"
"regexp"
"testing"

"github.com/containerd/nerdctl/v2/pkg/infoutil"
"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/testregistry"

"gotest.tools/v3/assert"
)
Expand Down Expand Up @@ -57,42 +57,21 @@ func TestIPFS(t *testing.T) {
base.Cmd("run", "--rm", decryptImageRef, "/bin/sh", "-c", "echo hello").AssertOK()
}

var iplineRegexp = regexp.MustCompile(`"([0-9\.]*)"`)

func TestIPFSAddress(t *testing.T) {
testutil.DockerIncompatible(t)
base := testutil.NewBase(t)
ipfsaddr, done := runIPFSDaemonContainer(t, base)
defer done()
iReg := testregistry.NewIPFSRegistry(base, nil, 0, nil, nil)
t.Cleanup(func() {
iReg.Cleanup(nil)
})
ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/%d", iReg.IP, iReg.Port)

ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", ipfsaddr))
base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs")
base.Cmd("pull", "--ipfs-address", ipfsaddr, ipfsCID).AssertOK()
base.Cmd("run", "--ipfs-address", ipfsaddr, "--rm", ipfsCID, "echo", "hello").AssertOK()
}

func runIPFSDaemonContainer(t *testing.T, base *testutil.Base) (ipfsAddress string, done func()) {
name := "test-ipfs-address"
var ipfsaddr string
if detachedNetNS, _ := rootlessutil.DetachedNetNS(); detachedNetNS != "" {
// detached-netns mode can't use .NetworkSettings.IPAddress, because the daemon and CNI has different network namespaces
base.Cmd("run", "-d", "-p", "127.0.0.1:5999:5999", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5999 && ipfs daemon --offline").AssertOK()
ipfsaddr = "/ip4/127.0.0.1/tcp/5999"
} else {
base.Cmd("run", "-d", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001 && ipfs daemon --offline").AssertOK()
iplines := base.Cmd("inspect", name, "-f", "'{{json .NetworkSettings.IPAddress}}'").OutLines()
t.Logf("IPAddress=%v", iplines)
assert.Equal(t, len(iplines), 2)
matches := iplineRegexp.FindStringSubmatch(iplines[0])
t.Logf("ip address matches=%v", matches)
assert.Equal(t, len(matches), 2)
ipfsaddr = fmt.Sprintf("/ip4/%s/tcp/5001", matches[1])
}
return ipfsaddr, func() {
base.Cmd("kill", "test-ipfs-address").AssertOK()
base.Cmd("rm", "test-ipfs-address").AssertOK()
}
}

func TestIPFSCommit(t *testing.T) {
// cgroup is required for nerdctl commit
if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" {
Expand Down
81 changes: 77 additions & 4 deletions pkg/testutil/testregistry/testregistry_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type TokenAuthServer struct {
func EnsureImages(base *testutil.Base) {
base.Cmd("pull", testutil.RegistryImage).AssertOK()
base.Cmd("pull", testutil.DockerAuthImage).AssertOK()
base.Cmd("pull", testutil.KuboImage).AssertOK()
}

func NewAuthServer(base *testutil.Base, ca *testca.CA, port int, user, pass string, tls bool) *TokenAuthServer {
Expand Down Expand Up @@ -112,6 +113,8 @@ acl:
port, err = portlock.Acquire(port)
assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err))
containerName := fmt.Sprintf("auth-%s-%d", name, port)
// Cleanup possible leftovers first
base.Cmd("rm", "-f", containerName).Run()

cleanup := func(err error) {
result := base.Cmd("rm", "-f", containerName).Run()
Expand Down Expand Up @@ -232,7 +235,78 @@ func (ba *BasicAuth) Params(base *testutil.Base) []string {
return ret
}

func NewIPFSRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundCleanup func(error)) *RegistryServer {
EnsureImages(base)

name := testutil.Identifier(base.T)
// listen on 0.0.0.0 to enable 127.0.0.1
listenIP := net.ParseIP("0.0.0.0")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not 127.0.0.1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it will not allow access using (non-localhost) host-ip, reducing possible test scope (comment is slightly misleading, originating from previous code in the registry start function).

hostIP, err := nettestutil.NonLoopbackIPv4()
assert.NilError(base.T, err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err))
port, err = portlock.Acquire(port)
assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err))

containerName := fmt.Sprintf("ipfs-registry-%s-%d", name, port)
// Cleanup possible leftovers first
base.Cmd("rm", "-f", containerName).Run()

args := []string{
"run",
"--pull=never",
"-d",
"-p", fmt.Sprintf("%s:%d:%d", listenIP, port, port),
"--name", containerName,
"--entrypoint=/bin/sh",
testutil.KuboImage,
"-c", "--",
fmt.Sprintf("ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/%d && ipfs daemon --offline", port),
}

cleanup := func(err error) {
result := base.Cmd("rm", "-f", containerName).Run()
errPortRelease := portlock.Release(port)
if boundCleanup != nil {
boundCleanup(err)
}
if err == nil {
assert.NilError(base.T, result.Error, fmt.Errorf("failed removing container: %w", err))
assert.NilError(base.T, errPortRelease, fmt.Errorf("failed releasing port: %w", err))
}
}

scheme := "http"

err = func() error {
cmd := base.Cmd(args...).Run()
if cmd.Error != nil {
base.T.Logf("%s:\n%s\n%s\n-------\n%s", containerName, cmd.Cmd, cmd.Stdout(), cmd.Stderr())
return cmd.Error
}

if _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s:%s/api/v0", scheme, hostIP.String(), strconv.Itoa(port)), 30, true); err != nil {
return err
}

return nil
}()

assert.NilError(base.T, err, fmt.Errorf("failed starting IPFS registry container in a timely manner: %w", err))

return &RegistryServer{
IP: hostIP,
Port: port,
Scheme: scheme,
ListenIP: listenIP,
Cleanup: cleanup,
Logs: func() {
base.T.Logf("%s: %q", containerName, base.Cmd("logs", containerName).Run().String())
},
}
}

func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundCleanup func(error)) *RegistryServer {
EnsureImages(base)

name := testutil.Identifier(base.T)
// listen on 0.0.0.0 to enable 127.0.0.1
listenIP := net.ParseIP("0.0.0.0")
Expand All @@ -242,6 +316,9 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC
assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err))

containerName := fmt.Sprintf("registry-%s-%d", name, port)
// Cleanup possible leftovers first
base.Cmd("rm", "-f", containerName).Run()

args := []string{
"run",
"--pull=never",
Expand Down Expand Up @@ -325,8 +402,6 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC
}()

if err != nil {
// cs := base.Cmd("inspect", containerName).Run()
// base.T.Logf("%s:\n%s\n%s\n=========================\n%s", containerName, cs.Cmd, cs.Stdout(), cs.Stderr())
cl := base.Cmd("logs", containerName).Run()
base.T.Logf("%s:\n%s\n%s\n=========================\n%s", containerName, cl.Cmd, cl.Stdout(), cl.Stderr())
cleanup(err)
Expand Down Expand Up @@ -357,8 +432,6 @@ func NewWithTokenAuth(base *testutil.Base, user, pass string, port int, tls bool
}

func NewWithNoAuth(base *testutil.Base, port int, tls bool) *RegistryServer {
EnsureImages(base)

var ca *testca.CA
if tls {
ca = testca.New(base.T)
Expand Down
Loading