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

[release/1.7] Cherry Pick Commits required to support dev containers using nerdctl and finch #3286

Closed
wants to merge 7 commits into from
Closed
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: 0 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ jobs:
containerd: v1.7.16
- ubuntu: 22.04
containerd: v1.7.16
- ubuntu: 22.04
containerd: main
env:
UBUNTU_VERSION: "${{ matrix.ubuntu }}"
CONTAINERD_VERSION: "${{ matrix.containerd }}"
Expand Down Expand Up @@ -168,10 +166,6 @@ jobs:
containerd: v1.7.16
rootlesskit: v1.1.1
target: test-integration-rootless
- ubuntu: 22.04
containerd: main
rootlesskit: v2.0.2
target: test-integration-rootless
- ubuntu: 20.04
containerd: v1.6.31
rootlesskit: v1.1.1
Expand All @@ -184,10 +178,6 @@ jobs:
containerd: v1.7.16
rootlesskit: v1.1.1
target: test-integration-rootless-port-slirp4netns
- ubuntu: 22.04
containerd: main
rootlesskit: v2.0.2
target: test-integration-rootless-port-slirp4netns
env:
UBUNTU_VERSION: "${{ matrix.ubuntu }}"
CONTAINERD_VERSION: "${{ matrix.containerd }}"
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
1511f6c003ace805eafeb1132727791326283cff88a923d76329e1892bba7a10 cni-plugins-linux-amd64-v1.4.1.tgz
72644e13557cda8a5b39baf97fc5e93d23fdf7baba7700000e7e9efd8bdf9234 cni-plugins-linux-arm64-v1.4.1.tgz
2a0ea7072d1806b8526489bcd3b4847a06ab010ee32ba3c3d4e5a3235d3eb138 cni-plugins-linux-amd64-v1.4.1.tgz
56fe62d73942cffd8f119d2b8ecb6a062e85f529a3dbfc7aa5cd83c2c01929a7 cni-plugins-linux-arm64-v1.4.1.tgz
36 changes: 33 additions & 3 deletions cmd/nerdctl/container_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"runtime"
"strings"

"github.com/containerd/console"
"github.com/containerd/log"
Expand Down Expand Up @@ -68,6 +69,7 @@ func newRunCommand() *cobra.Command {
setCreateFlags(runCommand)

runCommand.Flags().BoolP("detach", "d", false, "Run container in background and print container ID")
runCommand.Flags().StringSliceP("attach", "a", []string{}, "Attach STDIN, STDOUT, or STDERR")

return runCommand
}
Expand All @@ -78,6 +80,7 @@ func setCreateFlags(cmd *cobra.Command) {
cmd.Flags().Bool("help", false, "show help")

cmd.Flags().BoolP("tty", "t", false, "Allocate a pseudo-TTY")
cmd.Flags().Bool("sig-proxy", true, "Proxy received signals to the process (default true)")
cmd.Flags().BoolP("interactive", "i", false, "Keep STDIN open even if not attached")
cmd.Flags().String("restart", "no", `Restart policy to apply when a container exits (implemented values: "no"|"always|on-failure:n|unless-stopped")`)
cmd.RegisterFlagCompletionFunc("restart", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
Expand Down Expand Up @@ -283,6 +286,10 @@ func processCreateCommandFlagsInRun(cmd *cobra.Command) (opt types.ContainerCrea

opt.InRun = true

opt.SigProxy, err = cmd.Flags().GetBool("sig-proxy")
if err != nil {
return
}
opt.Interactive, err = cmd.Flags().GetBool("interactive")
if err != nil {
return
Expand All @@ -295,6 +302,23 @@ func processCreateCommandFlagsInRun(cmd *cobra.Command) (opt types.ContainerCrea
if err != nil {
return
}
opt.Attach, err = cmd.Flags().GetStringSlice("attach")
if err != nil {
return
}

validAttachFlag := true
for i, str := range opt.Attach {
opt.Attach[i] = strings.ToUpper(str)

if opt.Attach[i] != "STDIN" && opt.Attach[i] != "STDOUT" && opt.Attach[i] != "STDERR" {
validAttachFlag = false
}
}
if !validAttachFlag {
return opt, fmt.Errorf("invalid stream specified with -a flag. Valid streams are STDIN, STDOUT, and STDERR")
}

return opt, nil
}

Expand All @@ -316,6 +340,10 @@ func runAction(cmd *cobra.Command, args []string) error {
return errors.New("flags -d and --rm cannot be specified together")
}

if len(createOpt.Attach) > 0 && createOpt.Detach {
return errors.New("flags -d and -a cannot be specified together")
}

netFlags, err := loadNetworkFlags(cmd)
if err != nil {
return fmt.Errorf("failed to load networking flags: %s", err)
Expand Down Expand Up @@ -372,7 +400,7 @@ func runAction(cmd *cobra.Command, args []string) error {
}
logURI := lab[labels.LogURI]
detachC := make(chan struct{})
task, err := taskutil.NewTask(ctx, client, c, false, createOpt.Interactive, createOpt.TTY, createOpt.Detach,
task, err := taskutil.NewTask(ctx, client, c, createOpt.Attach, createOpt.Interactive, createOpt.TTY, createOpt.Detach,
con, logURI, createOpt.DetachKeys, createOpt.GOptions.Namespace, detachC)
if err != nil {
return err
Expand All @@ -390,8 +418,10 @@ func runAction(cmd *cobra.Command, args []string) error {
log.L.WithError(err).Error("console resize")
}
} else {
sigC := signalutil.ForwardAllSignals(ctx, task)
defer signalutil.StopCatch(sigC)
if createOpt.SigProxy {
sigC := signalutil.ForwardAllSignals(ctx, task)
defer signalutil.StopCatch(sigC)
}
}

statusC, err := task.Wait(ctx)
Expand Down
75 changes: 75 additions & 0 deletions cmd/nerdctl/container_run_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"runtime"
"strconv"
"strings"
"syscall"
"testing"
"time"

Expand Down Expand Up @@ -253,6 +254,80 @@ func TestRunTTY(t *testing.T) {
assert.Equal(t, 0, res.ExitCode, res.Combined())
}

func runSigProxy(t *testing.T, args ...string) (string, bool, bool) {
t.Parallel()
base := testutil.NewBase(t)
testContainerName := testutil.Identifier(t)
defer base.Cmd("rm", "-f", testContainerName).Run()

fullArgs := []string{"run"}
fullArgs = append(fullArgs, args...)
fullArgs = append(fullArgs,
"--name",
testContainerName,
testutil.CommonImage,
"sh",
"-c",
testutil.SigProxyTestScript,
)

result := base.Cmd(fullArgs...).Start()
process := result.Cmd.Process

// Waits until we reach the trap command in the shell script, then sends SIGINT.
time.Sleep(3 * time.Second)
syscall.Kill(process.Pid, syscall.SIGINT)

// Waits until SIGINT is sent and responded to, then kills process to avoid timeout
time.Sleep(3 * time.Second)
process.Kill()

sigIntRecieved := strings.Contains(result.Stdout(), testutil.SigProxyTrueOut)
timedOut := strings.Contains(result.Stdout(), testutil.SigProxyTimeoutMsg)

return result.Stdout(), sigIntRecieved, timedOut
}

func TestRunSigProxy(t *testing.T) {

type testCase struct {
name string
args []string
want bool
expectedOut string
}
testCases := []testCase{
{
name: "SigProxyDefault",
args: []string{},
want: true,
expectedOut: testutil.SigProxyTrueOut,
},
{
name: "SigProxyTrue",
args: []string{"--sig-proxy=true"},
want: true,
expectedOut: testutil.SigProxyTrueOut,
},
{
name: "SigProxyFalse",
args: []string{"--sig-proxy=false"},
want: false,
expectedOut: "",
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
stdout, sigIntRecieved, timedOut := runSigProxy(t, tc.args...)
errorMsg := fmt.Sprintf("%s failed;\nExpected: '%s'\nActual: '%s'", tc.name, tc.expectedOut, stdout)
assert.Equal(t, false, timedOut, errorMsg)
assert.Equal(t, tc.want, sigIntRecieved, errorMsg)
})
}
}

func TestRunWithFluentdLogDriver(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("fluentd log driver is not yet implemented on Windows")
Expand Down
120 changes: 120 additions & 0 deletions cmd/nerdctl/container_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,123 @@ func TestRunRmTime(t *testing.T) {
t.Fatalf("expected to have completed in %v, took %v", deadline, took)
}
}

func runAttachStdin(t *testing.T, testStr string, args []string) string {
if runtime.GOOS == "windows" {
t.Skip("run attach test is not yet implemented on Windows")
}

t.Parallel()
base := testutil.NewBase(t)
containerName := testutil.Identifier(t)

opts := []func(*testutil.Cmd){
testutil.WithStdin(strings.NewReader("echo " + testStr + "\nexit\n")),
}

fullArgs := []string{"run", "--rm", "-i"}
fullArgs = append(fullArgs, args...)
fullArgs = append(fullArgs,
"--name",
containerName,
testutil.CommonImage,
)

defer base.Cmd("rm", "-f", containerName).AssertOK()
result := base.Cmd(fullArgs...).CmdOption(opts...).Run()

return result.Combined()
}

func runAttach(t *testing.T, testStr string, args []string) string {
if runtime.GOOS == "windows" {
t.Skip("run attach test is not yet implemented on Windows")
}

t.Parallel()
base := testutil.NewBase(t)
containerName := testutil.Identifier(t)

fullArgs := []string{"run"}
fullArgs = append(fullArgs, args...)
fullArgs = append(fullArgs,
"--name",
containerName,
testutil.CommonImage,
"sh",
"-euxc",
"echo "+testStr,
)

defer base.Cmd("rm", "-f", containerName).AssertOK()
result := base.Cmd(fullArgs...).Run()

return result.Combined()
}

func TestRunAttachFlag(t *testing.T) {

type testCase struct {
name string
args []string
testFunc func(t *testing.T, testStr string, args []string) string
testStr string
expectedOut string
dockerOut string
}
testCases := []testCase{
{
name: "AttachFlagStdin",
args: []string{"-a", "STDIN", "-a", "STDOUT"},
testFunc: runAttachStdin,
testStr: "test-run-stdio",
expectedOut: "test-run-stdio",
dockerOut: "test-run-stdio",
},
{
name: "AttachFlagStdOut",
args: []string{"-a", "STDOUT"},
testFunc: runAttach,
testStr: "foo",
expectedOut: "foo",
dockerOut: "foo",
},
{
name: "AttachFlagMixedValue",
args: []string{"-a", "STDIN", "-a", "invalid-value"},
testFunc: runAttach,
testStr: "foo",
expectedOut: "invalid stream specified with -a flag. Valid streams are STDIN, STDOUT, and STDERR",
dockerOut: "valid streams are STDIN, STDOUT and STDERR",
},
{
name: "AttachFlagInvalidValue",
args: []string{"-a", "invalid-stream"},
testFunc: runAttach,
testStr: "foo",
expectedOut: "invalid stream specified with -a flag. Valid streams are STDIN, STDOUT, and STDERR",
dockerOut: "valid streams are STDIN, STDOUT and STDERR",
},
{
name: "AttachFlagCaseInsensitive",
args: []string{"-a", "stdin", "-a", "stdout"},
testFunc: runAttachStdin,
testStr: "test-run-stdio",
expectedOut: "test-run-stdio",
dockerOut: "test-run-stdio",
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
actualOut := tc.testFunc(t, tc.testStr, tc.args)
errorMsg := fmt.Sprintf("%s failed;\nExpected: '%s'\nActual: '%s'", tc.name, tc.expectedOut, actualOut)
if testutil.GetTarget() == testutil.Docker {
assert.Equal(t, true, strings.Contains(actualOut, tc.dockerOut), errorMsg)
} else {
assert.Equal(t, true, strings.Contains(actualOut, tc.expectedOut), errorMsg)
}
})
}
}
6 changes: 6 additions & 0 deletions cmd/nerdctl/system_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func newEventsCommand() *cobra.Command {
eventsCommand.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"json"}, cobra.ShellCompDirectiveNoFileComp
})
eventsCommand.Flags().StringSliceP("filter", "f", []string{}, "Filter matches containers based on given conditions")
return eventsCommand
}

Expand All @@ -51,10 +52,15 @@ func processSystemEventsOptions(cmd *cobra.Command) (types.SystemEventsOptions,
if err != nil {
return types.SystemEventsOptions{}, err
}
filters, err := cmd.Flags().GetStringSlice("filter")
if err != nil {
return types.SystemEventsOptions{}, err
}
return types.SystemEventsOptions{
Stdout: cmd.OutOrStdout(),
GOptions: globalOptions,
Format: format,
Filters: filters,
}, nil
}

Expand Down
Loading
Loading