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

Enable other containers to join network namespace of the none network #3443

Merged
merged 1 commit into from
Feb 15, 2025
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
332 changes: 304 additions & 28 deletions cmd/nerdctl/container/container_run_network_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -513,35 +512,197 @@ func TestRunNetworkHost2613(t *testing.T) {
base.Cmd("run", "--rm", "--add-host", "foo:1.2.3.4", testutil.CommonImage, "getent", "hosts", "foo").AssertOutExactly("1.2.3.4 foo foo\n")
}

func TestSharedNetworkStack(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("--network=container:<container name|id> only supports linux now")
}
base := testutil.NewBase(t)
func TestSharedNetworkSetup(t *testing.T) {
nerdtest.Setup()
testCase := &test.Case{
Require: test.Not(test.Windows),
Setup: func(data test.Data, helpers test.Helpers) {
data.Set("containerName1", data.Identifier("-container1"))
containerName1 := data.Get("containerName1")
helpers.Ensure("run", "-d", "--name", containerName1,
testutil.NginxAlpineImage)
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier("-container1"))
},
SubTests: []*test.Case{
{
Description: "Test network is shared",
NoParallel: true, // The validation involves starting of the main container: container1
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
containerName2 := data.Identifier()
cmd := helpers.Command()
cmd.WithArgs("run", "-d", "--name", containerName2,
"--network=container:"+data.Get("containerName1"),
testutil.NginxAlpineImage)
return cmd
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: func(stdout string, info string, t *testing.T) {
containerName2 := data.Identifier()
assert.Assert(t, strings.Contains(helpers.Capture("exec", containerName2, "wget", "-qO-", "http://127.0.0.1:80"), testutil.NginxAlpineIndexHTMLSnippet), info)
helpers.Ensure("restart", data.Get("containerName1"))
helpers.Ensure("stop", "--time=1", containerName2)
helpers.Ensure("start", containerName2)
assert.Assert(t, strings.Contains(helpers.Capture("exec", containerName2, "wget", "-qO-", "http://127.0.0.1:80"), testutil.NginxAlpineIndexHTMLSnippet), info)
},
}
},
},
{
Description: "Test uts is supported in shared network",
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
containerName2 := data.Identifier()
cmd := helpers.Command()
cmd.WithArgs("run", "-d", "--name", containerName2, "--uts", "host",
"--network=container:"+data.Get("containerName1"),
testutil.AlpineImage)
return cmd
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
ExitCode: 0,
}
},
},
{
Description: "Test dns is not supported",
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
containerName2 := data.Identifier()
cmd := helpers.Command()
cmd.WithArgs("run", "-d", "--name", containerName2, "--dns", "0.1.2.3",
"--network=container:"+data.Get("containerName1"),
testutil.AlpineImage)
return cmd
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
if nerdtest.IsDocker() {
return &test.Expected{
ExitCode: 125,
}

containerName := testutil.Identifier(t)
defer base.Cmd("rm", "-f", containerName).AssertOK()
base.Cmd("run", "-d", "--name", containerName,
testutil.NginxAlpineImage).AssertOK()
base.EnsureContainerStarted(containerName)
}
return &test.Expected{
ExitCode: 1,
}
},
},
{
Description: "Test dns options is not supported",
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
containerName2 := data.Identifier()
cmd := helpers.Command()
cmd.WithArgs("run", "--name", containerName2, "--dns-option", "attempts:5",
"--network=container:"+data.Get("containerName1"),
testutil.AlpineImage, "cat", "/etc/resolv.conf")
return cmd
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
// The Option doesnt throw an error but is never inserted to the resolv.conf
return &test.Expected{
ExitCode: 0,
Output: func(stdout string, info string, t *testing.T) {
assert.Assert(t, !strings.Contains(stdout, "attempts:5"), info)
},
}
},
},
{
Description: "Test publish is not supported",
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
containerName2 := data.Identifier()
cmd := helpers.Command()
cmd.WithArgs("run", "-d", "--name", containerName2, "--publish", "80:8080",
"--network=container:"+data.Get("containerName1"),
testutil.AlpineImage)
return cmd
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
if nerdtest.IsDocker() {
return &test.Expected{
ExitCode: 125,
}

}
return &test.Expected{
ExitCode: 1,
}
},
},
{
Description: "Test hostname is not supported",
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
containerName2 := data.Identifier()
cmd := helpers.Command()
cmd.WithArgs("run", "-d", "--name", containerName2, "--hostname", "test",
"--network=container:"+data.Get("containerName1"),
testutil.AlpineImage)
return cmd
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
if nerdtest.IsDocker() {
return &test.Expected{
ExitCode: 125,
}

}
return &test.Expected{
ExitCode: 1,
}
},
},
},
}
testCase.Run(t)
}

containerNameJoin := testutil.Identifier(t) + "-network"
defer base.Cmd("rm", "-f", containerNameJoin).AssertOK()
base.Cmd("run",
"-d",
"--name", containerNameJoin,
"--network=container:"+containerName,
testutil.CommonImage,
"sleep", nerdtest.Infinity).AssertOK()

base.Cmd("exec", containerNameJoin, "wget", "-qO-", "http://127.0.0.1:80").
AssertOutContains(testutil.NginxAlpineIndexHTMLSnippet)

base.Cmd("restart", containerName).AssertOK()
base.Cmd("stop", "--time=1", containerNameJoin).AssertOK()
base.Cmd("start", containerNameJoin).AssertOK()
base.Cmd("exec", containerNameJoin, "wget", "-qO-", "http://127.0.0.1:80").
AssertOutContains(testutil.NginxAlpineIndexHTMLSnippet)
func TestSharedNetworkWithNone(t *testing.T) {
nerdtest.Setup()
testCase := &test.Case{
Require: test.Not(test.Windows),
Setup: func(data test.Data, helpers test.Helpers) {
data.Set("containerName1", data.Identifier("-container1"))
containerName1 := data.Get("containerName1")
helpers.Ensure("run", "-d", "--name", containerName1, "--network", "none",
testutil.NginxAlpineImage)
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Get("containerName1"))
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
containerName2 := data.Identifier()
cmd := helpers.Command()
cmd.WithArgs("run", "-d", "--name", containerName2,
"--network=container:"+data.Get("containerName1"),
testutil.NginxAlpineImage)
return cmd
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
ExitCode: 0,
}
},
}
testCase.Run(t)
}

func TestRunContainerInExistingNetNS(t *testing.T) {
Expand Down Expand Up @@ -669,6 +830,8 @@ func TestHostsFileMounts(t *testing.T) {
"sh", "-euxc", "echo >> /etc/hosts").AssertOK()
base.Cmd("run", "--rm", "-v", "/etc/hosts:/etc/hosts", "--network", "host", testutil.CommonImage,
"sh", "-euxc", "head -n -1 /etc/hosts > temp && cat temp > /etc/hosts").AssertOK()
base.Cmd("run", "--rm", "--network", "none", testutil.CommonImage,
"sh", "-euxc", "echo >> /etc/hosts").AssertOK()

base.Cmd("run", "--rm", testutil.CommonImage,
"sh", "-euxc", "echo >> /etc/resolv.conf").AssertOK()
Expand All @@ -681,6 +844,8 @@ func TestHostsFileMounts(t *testing.T) {
"sh", "-euxc", "echo >> /etc/resolv.conf").AssertOK()
base.Cmd("run", "--rm", "-v", "/etc/resolv.conf:/etc/resolv.conf", "--network", "host", testutil.CommonImage,
"sh", "-euxc", "head -n -1 /etc/resolv.conf > temp && cat temp > /etc/resolv.conf").AssertOK()
base.Cmd("run", "--rm", "--network", "host", testutil.CommonImage,
"sh", "-euxc", "echo >> /etc/resolv.conf").AssertOK()
}

func TestRunContainerWithStaticIP6(t *testing.T) {
Expand Down Expand Up @@ -752,3 +917,114 @@ func TestRunContainerWithStaticIP6(t *testing.T) {
})
}
}

func TestNoneNetworkHostName(t *testing.T) {
nerdtest.Setup()
testCase := &test.Case{
Require: test.Not(test.Windows),
Setup: func(data test.Data, helpers test.Helpers) {
data.Set("containerName1", data.Identifier())
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("run", "-d", "--name", data.Identifier(), "--network", "none", testutil.NginxAlpineImage)
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: func(stdout string, info string, t *testing.T) {
hostname := stdout
if len(hostname) > 12 {
hostname = hostname[:12]
}
assert.Assert(t, strings.Compare(strings.TrimSpace(helpers.Capture("exec", data.Identifier(), "cat", "/etc/hostname")), hostname) == 0, info)
},
}
},
}
testCase.Run(t)
}

func TestHostNetworkHostName(t *testing.T) {
nerdtest.Setup()
testCase := &test.Case{
Require: test.Not(test.Windows),
Setup: func(data test.Data, helpers test.Helpers) {
data.Set("containerName1", data.Identifier())
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Custom("cat", "/etc/hostname")
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: func(stdout string, info string, t *testing.T) {
hostname := stdout
assert.Assert(t, strings.Compare(strings.TrimSpace(helpers.Capture("run", "--name", data.Identifier(), "--network", "host", testutil.AlpineImage, "cat", "/etc/hostname")), strings.TrimSpace(hostname)) == 0, info)
},
}
},
}
testCase.Run(t)
}

func TestNoneNetworkDnsConfigs(t *testing.T) {
nerdtest.Setup()
testCase := &test.Case{
Require: test.Not(test.Windows),
Setup: func(data test.Data, helpers test.Helpers) {
data.Set("containerName1", data.Identifier())
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("run", "-d", "--name", data.Identifier(), "--network", "none", "--dns", "0.1.2.3", "--dns-search", "example.com", "--dns-option", "timeout:3", "--dns-option", "attempts:5", testutil.NginxAlpineImage)
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: func(stdout string, info string, t *testing.T) {
out := helpers.Capture("exec", data.Identifier(), "cat", "/etc/resolv.conf")
assert.Assert(t, strings.Contains(out, "0.1.2.3"), info)
assert.Assert(t, strings.Contains(out, "example.com"), info)
assert.Assert(t, strings.Contains(out, "attempts:5"), info)
assert.Assert(t, strings.Contains(out, "timeout:3"), info)

},
}
},
}
testCase.Run(t)
}

func TestHostNetworkDnsConfigs(t *testing.T) {
nerdtest.Setup()
testCase := &test.Case{
Require: test.Not(test.Windows),
Setup: func(data test.Data, helpers test.Helpers) {
data.Set("containerName1", data.Identifier())
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rm", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("run", "-d", "--name", data.Identifier(), "--network", "host", "--dns", "0.1.2.3", "--dns-search", "example.com", "--dns-option", "timeout:3", "--dns-option", "attempts:5", testutil.NginxAlpineImage)
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: func(stdout string, info string, t *testing.T) {
out := helpers.Capture("exec", data.Identifier(), "cat", "/etc/resolv.conf")
assert.Assert(t, strings.Contains(out, "0.1.2.3"), info)
assert.Assert(t, strings.Contains(out, "example.com"), info)
assert.Assert(t, strings.Contains(out, "attempts:5"), info)
assert.Assert(t, strings.Contains(out, "timeout:3"), info)

},
}
},
}
testCase.Run(t)
}
6 changes: 6 additions & 0 deletions cmd/nerdctl/image/image_prune_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ func TestImagePrune(t *testing.T) {
// Cannot use a custom namespace with buildkitd right now, so, no parallel it is
testCase.NoParallel = true
testCase.Cleanup = func(data test.Data, helpers test.Helpers) {
// Stop and remove all running containers. This is to ensure we can remove all
contList := strings.TrimSpace(helpers.Capture("ps", "-aq"))
if contList != "" {
helpers.Ensure(append([]string{"rm", "-f"}, strings.Split(contList, "\n")...)...)
}

// We need to delete everything here for prune to make any sense
imgList := strings.TrimSpace(helpers.Capture("images", "--no-trunc", "-aq"))
if imgList != "" {
Expand Down
Loading