diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 049911e5df0..247bbe2b6e5 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -23,7 +23,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: read packages: write diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af5c1baa700..1fc1f70627c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,13 +9,13 @@ env: GO111MODULE: on jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 40 steps: - uses: actions/checkout@v4.1.1 - uses: actions/setup-go@v5 with: - go-version: 1.21.x + go-version: 1.23.x - name: "Compile binaries" run: make artifacts - name: "SHA256SUMS" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 49847eee123..675ed36ab89 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,12 +8,12 @@ on: pull_request: env: - GO_VERSION: 1.21.x + GO_VERSION: 1.23.x jobs: project: name: Project Checks - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v4.1.1 @@ -34,7 +34,7 @@ jobs: working-directory: src/github.com/containerd/nerdctl lint: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v4.1.1 @@ -46,15 +46,15 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v3.7.0 + uses: golangci/golangci-lint-action@v6.1.0 with: - version: v1.55.2 + version: v1.60.1 args: --verbose - name: yamllint-lint run: yamllint . test-unit: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v4.1.1 @@ -74,16 +74,20 @@ jobs: strategy: fail-fast: false matrix: - # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 + # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 20.04 containerd: v1.6.31 - ubuntu: 20.04 - containerd: v1.7.16 + containerd: v1.7.22 - ubuntu: 22.04 - containerd: v1.7.16 + containerd: v1.7.22 - ubuntu: 22.04 containerd: main + - ubuntu: 24.04 + containerd: v1.7.22 + - ubuntu: 24.04 + containerd: main env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -110,10 +114,10 @@ jobs: strategy: fail-fast: false matrix: - # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 + # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - - ubuntu: 22.04 - containerd: v1.7.16 + - ubuntu: 24.04 + containerd: v1.7.22 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -154,39 +158,55 @@ jobs: strategy: fail-fast: false matrix: - # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 + # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 20.04 containerd: v1.6.31 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.16 - rootlesskit: v2.0.2 + containerd: v1.7.22 + rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.16 + containerd: v1.7.22 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 - containerd: main - rootlesskit: v2.0.2 + containerd: main # v2.0.0-rc.X + rootlesskit: v2.3.1 + target: test-integration-rootless + - ubuntu: 24.04 + containerd: v1.7.22 + rootlesskit: v1.1.1 + target: test-integration-rootless + - ubuntu: 24.04 + containerd: main # v2.0.0-rc.X + rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 20.04 containerd: v1.6.31 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.16 - rootlesskit: v2.0.2 + containerd: v1.7.22 + rootlesskit: v2.3.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.16 + containerd: v1.7.22 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: main - rootlesskit: v2.0.2 + containerd: main # v2.0.0-rc.X + rootlesskit: v2.3.1 + target: test-integration-rootless-port-slirp4netns + - ubuntu: 24.04 + containerd: v1.7.22 + rootlesskit: v1.1.1 + target: test-integration-rootless-port-slirp4netns + - ubuntu: 24.04 + containerd: main # v2.0.0-rc.X + rootlesskit: v2.3.1 target: test-integration-rootless-port-slirp4netns env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" @@ -194,7 +214,22 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.1 + - name: "Set up AppArmor" + if: matrix.ubuntu == '24.04' + run: | + cat <, + include + + /usr/local/bin/rootlesskit flags=(unconfined) { + userns, + + # Site-specific additions and overrides. See local/README for details. + include if exists + } + EOT + sudo systemctl restart apparmor.service + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -205,11 +240,11 @@ jobs: run: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=1 ${TEST_TARGET} cross: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 40 strategy: matrix: - go-version: ["1.21.x", "1.22.x"] + go-version: ["1.22.x", "1.23.x"] steps: - uses: actions/checkout@v4.1.1 with: @@ -223,8 +258,8 @@ jobs: run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make artifacts test-integration-docker-compatibility: - runs-on: ubuntu-22.04 - timeout-minutes: 30 + runs-on: ubuntu-22.04 # TODO: ubuntu-24.04 + timeout-minutes: 45 steps: - uses: actions/checkout@v4.1.1 with: @@ -234,15 +269,25 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - - name: "Enable BuildKit" + - name: "Install Docker v24" run: | set -eux -o pipefail + # Uninstall the preinstalled Docker + sudo apt-get remove docker-* containerd.io # Enable BuildKit explicitly sudo apt-get install -y moreutils cat /etc/docker/daemon.json jq '.features.buildkit = true' sshd` here +# TODO: update containerized-systemd to enable sshd by default, or allow `systemctl wants ssh` here RUN ssh-keygen -q -t rsa -f /root/.ssh/id_rsa -N '' && \ useradd -m -s /bin/bash rootless && \ mkdir -p -m 0700 /home/rootless/.ssh && \ diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 new file mode 100644 index 00000000000..a662a4e6cd1 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 @@ -0,0 +1,2 @@ +59279df5853bef19a03ec15c5c31b772e59d91d079ab0221e1bafa023cf41c35 buildkit-v0.15.2.linux-amd64.tar.gz +15329adaa5e5b2bea0580f3e5e33765f84504075710bb791e362c3b160ca7e61 buildkit-v0.15.2.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 new file mode 100644 index 00000000000..6a91ab30028 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 @@ -0,0 +1,2 @@ +77baa2f669980a82255ffa2f2717de823992480271ee778aa51a9c60ae89ff9b cni-plugins-linux-amd64-v1.5.1.tgz +c2a292714d0fad98a3491ae43df8ad58354b3c0bdf5d5a3e281777967c70fcff cni-plugins-linux-arm64-v1.5.1.tgz diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 new file mode 100644 index 00000000000..b624de1f641 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 @@ -0,0 +1,6 @@ +57bc67f71b8043961417325be13528d4f1e8ec90876cd34c38064431f457070f rootlesskit-aarch64.tar.gz +5154542509736957738478e3624b53865a875c396f978db5adea513d7507dee6 rootlesskit-armv7l.tar.gz +983642556dd3dcbe2c9b764d577882016ad1ca960815ffa13ca76d7da518504f rootlesskit-ppc64le.tar.gz +83c40bb8938828eb15837a4900ba825a1f52227631195c22df85f2e8f7f73546 rootlesskit-riscv64.tar.gz +dd6c8bc7e1c9b5d8c775efcf40854ef1d25205060294f0654a77d996a7f4e172 rootlesskit-s390x.tar.gz +caafdce18e0959f078b4b478d4f352ebf3d556e373265fc7831f1a6d70219ee0 rootlesskit-x86_64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.1 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.1 new file mode 100644 index 00000000000..4d0d9ea9444 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.1 @@ -0,0 +1,6 @@ +2dd9aac6c2e3203e53cb7b6e4b9fc7123e4e4a9716c8bb1d95951853059a6af5 slirp4netns-aarch64 +ed618c0f2c74014bb736e9e427e18c8791ad9d68311872a41b06fac0d7cb9ef2 slirp4netns-armv7l +a10f70209cee0dd0532fea0e8b6bfde5d16dec5206fd4b3387d861721456de66 slirp4netns-ppc64le +38209015c2f3f4619d9fc46610852887910f33c7a0b96f7d2aa835a7bbc73f31 slirp4netns-riscv64 +9f42718455b1f9cf4b6f0efee314b78e860b8c36dbbb6290f09c8fbedda9ff8a slirp4netns-s390x +4bc5d6c311f9fa7ae00ce54aefe10c2afaf0800fe9e99f32616a964ed804a9e1 slirp4netns-x86_64 diff --git a/Dockerfile.d/test-integration-rootless.sh b/Dockerfile.d/test-integration-rootless.sh index 00975410f7f..0e2cb929b4f 100755 --- a/Dockerfile.d/test-integration-rootless.sh +++ b/Dockerfile.d/test-integration-rootless.sh @@ -27,7 +27,7 @@ if [[ "$(id -u)" = "0" ]]; then fi # Switch to the rootless user via SSH - systemctl start sshd + systemctl start ssh exec ssh -o StrictHostKeyChecking=no rootless@localhost "$0" "$@" else containerd-rootless-setuptool.sh install @@ -48,7 +48,7 @@ else [proxy_plugins] [proxy_plugins."stargz"] type = "snapshot" - address = "/run/user/1000/containerd-stargz-grpc/containerd-stargz-grpc.sock" + address = "/run/user/$(id -u)/containerd-stargz-grpc/containerd-stargz-grpc.sock" EOF systemctl --user restart containerd.service containerd-rootless-setuptool.sh -- install-ipfs --init --offline # offline ipfs daemon for testing diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index f12dc530fa2..0beead9ed11 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -21,7 +21,6 @@ import ( "fmt" "net" "os" - "runtime" "strings" "testing" @@ -98,7 +97,7 @@ services: if !strings.Contains(stdout, "\nBAR=bar1 bar2\n") { return errors.New("got bad BAR") } - if !strings.Contains(stdout, "\nBAZ=\n") && runtime.GOOS != "windows" { + if !strings.Contains(stdout, "\nBAZ=\n") { return errors.New("got bad BAZ") } if strings.Contains(stdout, "QUX") { @@ -113,10 +112,10 @@ services: if !strings.Contains(stdout, "\nGRAULT=grault_key=grault_value\n") { return errors.New("got bad GRAULT") } - if !strings.Contains(stdout, "\nGARPLY=\n") && runtime.GOOS != "windows" { + if !strings.Contains(stdout, "\nGARPLY=\n") { return errors.New("got bad GARPLY") } - if !strings.Contains(stdout, "\nWALDO=\n") && runtime.GOOS != "windows" { + if !strings.Contains(stdout, "\nWALDO=\n") { return errors.New("got bad WALDO") } diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index e9e569584fb..07cd60bdfba 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -24,8 +24,8 @@ import ( "time" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/restart" + "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/clientutil" diff --git a/cmd/nerdctl/compose_start.go b/cmd/nerdctl/compose_start.go index a5889b18aaa..b3e956e7264 100644 --- a/cmd/nerdctl/compose_start.go +++ b/cmd/nerdctl/compose_start.go @@ -22,7 +22,7 @@ import ( "os" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/compose" "github.com/containerd/nerdctl/pkg/containerutil" diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index 403d463de8d..50e1578b84e 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container_create_linux_test.go @@ -18,7 +18,6 @@ package main import ( "fmt" - "runtime" "testing" "github.com/containerd/nerdctl/pkg/testutil" @@ -57,9 +56,9 @@ func TestCreateWithMACAddress(t *testing.T) { WantErr bool Expect string }{ - {"host", true, "conflicting options"}, + {"host", true, ""}, {"none", true, "can't open '/sys/class/net/eth0/address'"}, - {"container:whatever" + tID, true, "conflicting options"}, + {"container:whatever" + tID, true, ""}, {"bridge", false, ""}, {networkBridge, false, ""}, {networkMACvlan, false, ""}, @@ -113,9 +112,6 @@ func TestCreateWithMACAddress(t *testing.T) { } func TestCreateWithTty(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("json-file log driver is not yet implemented on Windows") - } base := testutil.NewBase(t) imageName := testutil.CommonImage withoutTtyContainerName := "without-terminal-" + testutil.Identifier(t) diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 48db2be7891..3346bd612de 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -26,7 +26,6 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/leases" "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/platforms" "github.com/containerd/continuity/fs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" @@ -35,6 +34,7 @@ import ( "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/platforms" "github.com/opencontainers/image-spec/identity" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index c1684e17e7a..5eff72b395b 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "runtime" + "strings" "github.com/containerd/console" "github.com/containerd/log" @@ -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 } @@ -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) { @@ -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 @@ -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 } @@ -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) @@ -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 @@ -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) diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index 0301ae58e66..aa70c57cad4 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container_run_cgroup_linux_test.go @@ -24,10 +24,10 @@ import ( "testing" "github.com/containerd/cgroups/v3" - "github.com/containerd/containerd/pkg/userns" "github.com/containerd/continuity/testutil/loopback" "github.com/containerd/nerdctl/pkg/cmd/container" "github.com/containerd/nerdctl/pkg/testutil" + "github.com/moby/sys/userns" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index 678ea108d46..0900489f914 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -26,9 +26,9 @@ import ( "net/http" "os" "path/filepath" - "runtime" "strconv" "strings" + "syscall" "testing" "time" @@ -253,10 +253,81 @@ func TestRunTTY(t *testing.T) { assert.Equal(t, 0, res.ExitCode, res.Combined()) } -func TestRunWithFluentdLogDriver(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("fluentd log driver is not yet implemented on Windows") +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) { base := testutil.NewBase(t) tempDirectory := t.TempDir() err := os.Chmod(tempDirectory, 0777) @@ -286,9 +357,6 @@ func TestRunWithFluentdLogDriver(t *testing.T) { } func TestRunWithFluentdLogDriverWithLogOpt(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("fluentd log driver is not yet implemented on Windows") - } base := testutil.NewBase(t) tempDirectory := t.TempDir() err := os.Chmod(tempDirectory, 0777) diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 62d6ad978cc..95fdbc41f99 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -25,7 +25,7 @@ import ( "strings" "testing" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" @@ -354,12 +354,16 @@ func TestRunContainerWithStaticIP(t *testing.T) { useNetwork: true, checkTheIPAddress: false, }, - { - ip: "10.4.0.2", - shouldSuccess: true, - useNetwork: false, - checkTheIPAddress: false, - }, + // XXX see https://github.com/containerd/nerdctl/issues/3101 + // seems the incompatibility is coming from CNI plugin upgrade. This test has been disabled in main. + /* + { + ip: "10.4.0.2", + shouldSuccess: true, + useNetwork: false, + checkTheIPAddress: false, + }, + */ } tID := testutil.Identifier(t) for i, tc := range testCases { diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index e18aa7ac8e6..52b01281321 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -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) + } + }) + } +} diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 73b39588271..e153544d92d 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -24,8 +24,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/cri/util" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" diff --git a/cmd/nerdctl/image_convert_linux_test.go b/cmd/nerdctl/image_convert_linux_test.go index 4b7eff95856..29767454653 100644 --- a/cmd/nerdctl/image_convert_linux_test.go +++ b/cmd/nerdctl/image_convert_linux_test.go @@ -18,7 +18,6 @@ package main import ( "fmt" - "runtime" "testing" "github.com/containerd/nerdctl/pkg/rootlessutil" @@ -28,9 +27,6 @@ import ( ) func TestImageConvertNydus(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("no windows support yet") - } testutil.RequireExecutable(t, "nydus-image") testutil.DockerIncompatible(t) base := testutil.NewBase(t) diff --git a/cmd/nerdctl/login_linux_test.go b/cmd/nerdctl/login_linux_test.go index 12fbc8d4377..a1bc24655d8 100644 --- a/cmd/nerdctl/login_linux_test.go +++ b/cmd/nerdctl/login_linux_test.go @@ -71,7 +71,7 @@ func TestLoginWithSpecificRegHosts(t *testing.T) { }, } for _, tc := range testCases { - t.Logf(tc.log) + t.Log(tc.log) base.Cmd("--debug-full", "--hosts-dir", reg.HostsDir, "login", "-u", "admin", "-p", "validTestPassword", tc.url).AssertOK() } diff --git a/cmd/nerdctl/network_inspect_test.go b/cmd/nerdctl/network_inspect_test.go index 76b93ec7097..8ccfa474b32 100644 --- a/cmd/nerdctl/network_inspect_test.go +++ b/cmd/nerdctl/network_inspect_test.go @@ -34,7 +34,7 @@ func TestNetworkInspect(t *testing.T) { const ( testSubnet = "10.24.24.0/24" testGateway = "10.24.24.1" - testIPRange = "10.24.24.1/25" + testIPRange = "10.24.24.0/25" ) base := testutil.NewBase(t) diff --git a/cmd/nerdctl/system_events.go b/cmd/nerdctl/system_events.go index 9455cd1ca59..015c3b0d253 100644 --- a/cmd/nerdctl/system_events.go +++ b/cmd/nerdctl/system_events.go @@ -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 } @@ -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 } diff --git a/cmd/nerdctl/system_events_linux_test.go b/cmd/nerdctl/system_events_linux_test.go new file mode 100644 index 00000000000..6d9e027ece7 --- /dev/null +++ b/cmd/nerdctl/system_events_linux_test.go @@ -0,0 +1,111 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/containerd/nerdctl/pkg/testutil" + "gotest.tools/v3/assert" +) + +func testEventFilter(t *testing.T, args ...string) string { + t.Parallel() + base := testutil.NewBase(t) + testContainerName := testutil.Identifier(t) + defer base.Cmd("rm", "-f", testContainerName).Run() + + fullArgs := []string{"events", "--filter"} + fullArgs = append(fullArgs, args...) + fullArgs = append(fullArgs, + "--format", + "json", + ) + + eventsCmd := base.Cmd(fullArgs...).Start() + base.Cmd("run", "--rm", testutil.CommonImage).Start() + time.Sleep(3 * time.Second) + return eventsCmd.Stdout() +} + +func TestEventFilters(t *testing.T) { + + type testCase struct { + name string + args []string + nerdctlOut string + dockerOut string + dockerSkip bool + } + testCases := []testCase{ + { + name: "CapitializedFilter", + args: []string{"event=START"}, + nerdctlOut: "\"Status\":\"start\"", + dockerOut: "\"status\":\"start\"", + dockerSkip: true, + }, + { + name: "StartEventFilter", + args: []string{"event=start"}, + nerdctlOut: "\"Status\":\"start\"", + dockerOut: "\"status\":\"start\"", + dockerSkip: false, + }, + { + name: "UnsupportedEventFilter", + args: []string{"event=unknown"}, + nerdctlOut: "\"Status\":\"unknown\"", + dockerSkip: true, + }, + { + name: "StatusFilter", + args: []string{"status=start"}, + nerdctlOut: "\"Status\":\"start\"", + dockerOut: "\"status\":\"start\"", + dockerSkip: false, + }, + { + name: "UnsupportedStatusFilter", + args: []string{"status=unknown"}, + nerdctlOut: "\"Status\":\"unknown\"", + dockerSkip: true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + actualOut := testEventFilter(t, tc.args...) + errorMsg := fmt.Sprintf("%s failed;\nActual Filter Result: '%s'", tc.name, actualOut) + + isDocker := testutil.GetTarget() == testutil.Docker + if isDocker && tc.dockerSkip { + t.Skip("test is incompatible with Docker") + } + + if isDocker { + assert.Equal(t, true, strings.Contains(actualOut, tc.dockerOut), errorMsg) + } else { + assert.Equal(t, true, strings.Contains(actualOut, tc.nerdctlOut), errorMsg) + } + }) + } +} diff --git a/docs/command-reference.md b/docs/command-reference.md index cbd79627998..638e2b0676d 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -137,9 +137,11 @@ Usage: `nerdctl run [OPTIONS] IMAGE [COMMAND] [ARG...]` Basic flags: +- :whale: `-a, --attach`: Attach STDIN, STDOUT, or STDERR - :whale: :blue_square: `-i, --interactive`: Keep STDIN open even if not attached" - :whale: :blue_square: `-t, --tty`: Allocate a pseudo-TTY - :warning: WIP: currently `-t` conflicts with `-d` +- :whale: `-sig-proxy`: Proxy received signals to the process (default true) - :whale: :blue_square: `-d, --detach`: Run container in background and print container ID - :whale: `--restart=(no|always|on-failure|unless-stopped)`: Restart policy to apply when a container exits - Default: "no" @@ -376,9 +378,9 @@ IPFS flags: - :nerd_face: `--ipfs-address`: Multiaddr of IPFS API (default uses `$IPFS_PATH` env variable if defined or local directory `~/.ipfs`) Unimplemented `docker run` flags: - `--attach`, `--blkio-weight-device`, `--cpu-rt-*`, `--device-*`, + `--blkio-weight-device`, `--cpu-rt-*`, `--device-*`, `--disable-content-trust`, `--domainname`, `--expose`, `--health-*`, `--isolation`, `--no-healthcheck`, - `--link*`, `--mac-address`, `--publish-all`, `--sig-proxy`, `--storage-opt`, + `--link*`, `--mac-address`, `--publish-all`, `--storage-opt`, `--userns`, `--volume-driver` ### :whale: :blue_square: nerdctl exec @@ -1256,8 +1258,10 @@ Usage: `nerdctl events [OPTIONS]` Flags: - :whale: `--format`: Format the output using the given Go template, e.g, `{{json .}}` +- :whale: `-f, --filter`: Filter containers based on given conditions + - :whale: `--filter event=`: Event's status. Start is the only supported status. -Unimplemented `docker events` flags: `--filter`, `--since`, `--until` +Unimplemented `docker events` flags: `--since`, `--until` ### :whale: nerdctl info diff --git a/go.mod b/go.mod index a23cc4a3bc7..e43c1699719 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,15 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 - github.com/Microsoft/go-winio v0.6.1 - github.com/Microsoft/hcsshim v0.11.4 + github.com/Microsoft/go-winio v0.6.2 + github.com/Microsoft/hcsshim v0.11.7 github.com/awslabs/soci-snapshotter v0.4.1 github.com/compose-spec/compose-go v1.20.2 - github.com/containerd/accelerated-container-image v1.0.2 + github.com/containerd/accelerated-container-image v1.1.2 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.16 + github.com/containerd/containerd v1.7.22 + github.com/containerd/containerd/api v1.7.19 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 @@ -42,7 +43,7 @@ require ( github.com/moby/term v0.5.0 github.com/muesli/cancelreader v0.2.2 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc5 + github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.1.0 github.com/pelletier/go-toml/v2 v2.1.1 github.com/rootless-containers/bypass4netns v0.4.0 @@ -64,8 +65,6 @@ require ( gotest.tools/v3 v3.5.1 ) -require github.com/moby/sys/user v0.1.0 // indirect - require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect @@ -73,11 +72,13 @@ require ( github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.11.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect + github.com/containerd/errdefs v0.1.0 github.com/containerd/go-runc v1.0.0 // indirect - github.com/containerd/ttrpc v1.2.3 // indirect + github.com/containerd/platforms v0.2.1 + github.com/containerd/ttrpc v1.2.5 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect - github.com/containers/ocicrypt v1.1.9 // indirect - github.com/distribution/reference v0.5.0 // indirect + github.com/containers/ocicrypt v1.1.10 // indirect + github.com/distribution/reference v0.6.0 github.com/djherbis/times v1.5.0 // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect @@ -90,7 +91,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -106,6 +107,8 @@ require ( github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/symlink v0.2.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect + github.com/moby/sys/userns v0.1.0 github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.1.0 // indirect @@ -119,7 +122,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect + github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tinylib/msgp v1.1.6 // indirect @@ -130,14 +133,12 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect + go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/tools v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.33.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/go.sum b/go.sum index 4d9e9610899..723f2a360a0 100644 --- a/go.sum +++ b/go.sum @@ -10,10 +10,10 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8 github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ= +github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= github.com/awslabs/soci-snapshotter v0.4.1 h1:f1TdTG5QZ1B6umgSPQfM1pSXDlMZu+raCKWP4QkRYL8= github.com/awslabs/soci-snapshotter v0.4.1/go.mod h1:faOXa3a6SsMRln4misZi82nAa4ez8Nu9i5N39kQyukY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -28,8 +28,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ= github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= -github.com/containerd/accelerated-container-image v1.0.2 h1:4GmZg/8TrxAbTTpighuipeFPrjqH1ZKZgoa4bggMZVs= -github.com/containerd/accelerated-container-image v1.0.2/go.mod h1:0/cMmA65Zervb+pO+sZvxvhqiO/pWoKdTf2zgbh59Zo= +github.com/containerd/accelerated-container-image v1.1.2 h1:Gk+1aqi6DpMVPCFAFWAUZgeKzSQ8fEu+GiBLnS42rc4= +github.com/containerd/accelerated-container-image v1.1.2/go.mod h1:NcMeDHjzY1cH5E96knLx0QaGYHeUxe0z3zA2/8qh1IE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= @@ -37,10 +37,14 @@ github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2 github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/containerd/containerd v1.7.16 h1:7Zsfe8Fkj4Wi2My6DXGQ87hiqIrmOXolm72ZEkFU5Mg= -github.com/containerd/containerd v1.7.16/go.mod h1:NL49g7A/Fui7ccmxV6zkBWwqMgmMxFWzujYCc+JLt7k= +github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= +github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= +github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= +github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= +github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9rU= @@ -53,14 +57,16 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/nydus-snapshotter v0.13.4 h1:veTQCgpfRGdPD031dVNGlU+vK/W9vBhZNlMWR9oupiQ= github.com/containerd/nydus-snapshotter v0.13.4/go.mod h1:y41TM10lXhskfHHvge7kf1VucM4CeWwsCmQ5Q51UJrc= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= github.com/containerd/stargz-snapshotter v0.15.1/go.mod h1:74D+J1m1RMXytLmWxegXWhtOSRHPWZKpKc2NdK3S+us= github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU= github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= github.com/containerd/stargz-snapshotter/ipfs v0.15.1 h1:MMWRYrTu2iVOn9eRJqEer7v0eg34xY2uFZxbrrm2iCY= github.com/containerd/stargz-snapshotter/ipfs v0.15.1/go.mod h1:DvrczCWAJnbTOau8txguZXDZdA7r39O3/Aj2olx+Q90= -github.com/containerd/ttrpc v1.2.3 h1:4jlhbXIGvijRtNC8F/5CpuJZ7yKOBFGFOOXg1bkISz0= -github.com/containerd/ttrpc v1.2.3/go.mod h1:ieWsXucbb8Mj9PH0rXCw1i8IunRbbAiDkpXkbfflWBM= +github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= +github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 h1:rQvjv7gRi6Ki/NS/U9oLZFhqyk4dh/GH2M3o/4BRkMM= github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67/go.mod h1:HDkcKOXRnX6yKnXv3P0QrogFi0DoiauK/LpQi961f0A= github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= @@ -69,8 +75,8 @@ github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl3 github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= github.com/containernetworking/plugins v1.4.0 h1:+w22VPYgk7nQHw7KT92lsRmuToHvb7wwSv9iTbXzzic= github.com/containernetworking/plugins v1.4.0/go.mod h1:UYhcOyjefnrQvKvmmyEKsUA+M9Nfn7tqULPpH0Pkcj0= -github.com/containers/ocicrypt v1.1.9 h1:2Csfba4jse85Raxk5HIyEk8OwZNjRvfkhEGijOjIdEM= -github.com/containers/ocicrypt v1.1.9/go.mod h1:dTKx1918d8TDkxXvarscpNVY+lyPakPNFN4jwA9GBys= +github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic= +github.com/containers/ocicrypt v1.1.10/go.mod h1:YfzSSr06PTHQwSTUKqDSjish9BeW1E4HUmreluQcMd8= github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8= github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -83,8 +89,8 @@ github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxG github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.5.0 h1:79myA211VwPhFTqUk8xehWrsEO+zcIZj0zT8mXPVARU= github.com/djherbis/times v1.5.0/go.mod h1:5q7FDLvbNg1L/KaBmPcWlVR9NmoKo3+ucqUA3ijQhA0= github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= @@ -163,8 +169,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -216,8 +222,10 @@ github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc= github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= -github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -252,8 +260,8 @@ github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -288,8 +296,8 @@ github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= +github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= @@ -336,12 +344,12 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= @@ -363,8 +371,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -463,10 +469,10 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a h1:fwgW9j3vHirt4ObdHoYNwuO24BEZjSzbh+zPaNWoiY8= -google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:EMfReVxb80Dq1hhioy0sOsY9jCE46YDgHlJ7fWVUWRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/hack/build-integration-kube.sh b/hack/build-integration-kube.sh new file mode 100755 index 00000000000..52ae61ca25a --- /dev/null +++ b/hack/build-integration-kube.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +# Copyright The containerd Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# shellcheck disable=SC2034,SC2015 +set -o errexit -o errtrace -o functrace -o nounset -o pipefail +root="$(cd "$(dirname "${BASH_SOURCE[0]:-$PWD}")" 2>/dev/null 1>&2 && pwd)" +readonly root +# shellcheck source=/dev/null +. "$root/scripts/lib.sh" + +GO_VERSION=1.23 +KIND_VERSION=v0.23.0 + +[ "$(uname -m)" == "aarch64" ] && GOARCH=arm64 || GOARCH=amd64 + +_rootful= + +configure::rootful(){ + log::debug "Configuring rootful to: ${1:+true}" + _rootful="${1:+true}" +} + +install::kind(){ + local version="$1" + local temp + temp="$(fs::mktemp "install")" + + http::get "$temp"/kind "https://kind.sigs.k8s.io/dl/$version/kind-linux-${GOARCH:-amd64}" + host::install "$temp"/kind +} + +# shellcheck disable=SC2120 +install::kubectl(){ + local version="${1:-}" + [ "$version" ] || version="$(http::get /dev/stdout https://dl.k8s.io/release/stable.txt)" + local temp + temp="$(fs::mktemp "install")" + + http::get "$temp"/kubectl "https://storage.googleapis.com/kubernetes-release/release/$version/bin/linux/${GOARCH:-amd64}/kubectl" + host::install "$temp"/kubectl +} + +exec::kind(){ + local args=() + [ ! "$_rootful" ] || args=(sudo env PATH="$PATH" KIND_EXPERIMENTAL_PROVIDER="$KIND_EXPERIMENTAL_PROVIDER") + args+=(kind) + + log::debug "${args[*]} $*" + "${args[@]}" "$@" +} + +exec::nerdctl(){ + local args=() + [ ! "$_rootful" ] || args=(sudo env PATH="$PATH") + args+=("$(pwd)"/_output/nerdctl) + + log::debug "${args[*]} $*" + "${args[@]}" "$@" +} + +# Install dependencies +main(){ + log::info "Configuring rootful" + configure::rootful "${ROOTFUL:-}" + + log::info "Installing host dependencies if necessary" + host::require kind 2>/dev/null || install::kind "$KIND_VERSION" + host::require kubectl 2>/dev/null || install::kubectl + + # Build nerdctl to use for kind + make binaries + PATH=$(pwd)/_output:"$PATH" + export PATH + + # Hack to get go into kind control plane + exec::nerdctl rm -f go-kind 2>/dev/null || true + exec::nerdctl run -d --name go-kind golang:"$GO_VERSION" sleep Inf + exec::nerdctl cp go-kind:/usr/local/go /tmp/go + + # Create fresh cluster + log::info "Creating new cluster" + export KIND_EXPERIMENTAL_PROVIDER=nerdctl + exec::kind delete cluster --name nerdctl-test 2>/dev/null || true + exec::kind create cluster --name nerdctl-test --config=./hack/kind.yaml +} + +main "$@" \ No newline at end of file diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 4c30443b990..b9e647579aa 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -62,10 +62,14 @@ type ContainerCreateOptions struct { Interactive bool // TTY specifies whether to allocate a pseudo-TTY for the container TTY bool + // SigProxy specifies whether to proxy all received signals to the process + SigProxy bool // Detach runs container in background and print container ID Detach bool // The key sequence for detaching a container. DetachKeys string + // Attach STDIN, STDOUT, or STDERR + Attach []string // Restart specifies the policy to apply when a container exits Restart string // Rm specifies whether to remove the container automatically when it exits diff --git a/pkg/api/types/system_types.go b/pkg/api/types/system_types.go index 65df3218674..bfadba7a057 100644 --- a/pkg/api/types/system_types.go +++ b/pkg/api/types/system_types.go @@ -37,6 +37,8 @@ type SystemEventsOptions struct { GOptions GlobalCommandOptions // Format the output using the given Go template, e.g, '{{json .}} Format string + // Filter events based on given conditions + Filters []string } // SystemPruneOptions specifies options for `nerdctl system prune`. diff --git a/pkg/apparmorutil/apparmorutil_linux.go b/pkg/apparmorutil/apparmorutil_linux.go index 38ea38c7f2d..b67ab7ff28c 100644 --- a/pkg/apparmorutil/apparmorutil_linux.go +++ b/pkg/apparmorutil/apparmorutil_linux.go @@ -24,8 +24,8 @@ import ( "sync" "github.com/containerd/containerd/pkg/apparmor" - "github.com/containerd/containerd/pkg/userns" "github.com/containerd/log" + "github.com/moby/sys/userns" ) // CanLoadNewProfile returns whether the current process can load a new AppArmor profile. diff --git a/pkg/bypass4netnsutil/bypass.go b/pkg/bypass4netnsutil/bypass.go index b5497d3bba8..e3fc7739962 100644 --- a/pkg/bypass4netnsutil/bypass.go +++ b/pkg/bypass4netnsutil/bypass.go @@ -22,7 +22,7 @@ import ( "net" "path/filepath" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" b4nnapi "github.com/rootless-containers/bypass4netns/pkg/api" "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" diff --git a/pkg/clientutil/client.go b/pkg/clientutil/client.go index 5f3aa4e82eb..b9c9782d7a9 100644 --- a/pkg/clientutil/client.go +++ b/pkg/clientutil/client.go @@ -26,10 +26,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/platforms" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/systemutil" + "github.com/containerd/platforms" "github.com/opencontainers/go-digest" ) diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index fa2feeaa085..5b675564260 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -29,17 +29,17 @@ import ( "strings" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/archive" - "github.com/containerd/containerd/platforms" - dockerreference "github.com/containerd/containerd/reference/docker" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/buildkitutil" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/platforms" + dockerreference "github.com/distribution/reference" ) func Build(ctx context.Context, client *containerd.Client, options types.BuilderBuildOptions) error { diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 65be64b8965..299b186c192 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -24,8 +24,7 @@ import ( "path/filepath" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/platforms" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/cmd/volume" "github.com/containerd/nerdctl/pkg/composer" @@ -36,6 +35,7 @@ import ( "github.com/containerd/nerdctl/pkg/referenceutil" "github.com/containerd/nerdctl/pkg/signutil" "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 6c0f7031752..c64377abaa9 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/containerutil" diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index 97f6033f9f8..278d9580d9a 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -26,8 +26,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/progress" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/formatter" diff --git a/pkg/cmd/container/logs.go b/pkg/cmd/container/logs.go index 239074c36cd..8104e8ad6c3 100644 --- a/pkg/cmd/container/logs.go +++ b/pkg/cmd/container/logs.go @@ -24,7 +24,7 @@ import ( "syscall" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/api/types/cri" diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 11e4a91c230..69cfe2ea2f4 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -27,8 +27,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index cf22e642715..2d765809e7a 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -24,7 +24,6 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/userns" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/bypass4netnsutil" @@ -33,6 +32,7 @@ import ( "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/strutil" "github.com/docker/go-units" + "github.com/moby/sys/userns" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index be29aa6f164..142ed509177 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -29,12 +29,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/leases" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/userns" "github.com/containerd/continuity/fs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/cmd/volume" @@ -46,6 +45,7 @@ import ( "github.com/containerd/nerdctl/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/pkg/strutil" securejoin "github.com/cyphar/filepath-securejoin" + "github.com/moby/sys/userns" "github.com/opencontainers/image-spec/identity" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index 64811db4c72..ecf91213381 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -29,8 +29,8 @@ import ( "github.com/containerd/containerd" eventstypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" @@ -81,14 +81,14 @@ func (s *stats) isKnownContainer(cid string) (int, bool) { } // Stats displays a live stream of container(s) resource usage statistics. -func Stats(ctx context.Context, client *containerd.Client, containerIds []string, options types.ContainerStatsOptions) error { +func Stats(ctx context.Context, client *containerd.Client, containerIDs []string, options types.ContainerStatsOptions) error { // NOTE: rootless container does not rely on cgroupv1. // more details about possible ways to resolve this concern: #223 if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { return errors.New("stats requires cgroup v2 for rootless containers, see https://rootlesscontaine.rs/getting-started/common/cgroup2/") } - showAll := len(containerIds) == 0 + showAll := len(containerIDs) == 0 closeChan := make(chan error) var err error @@ -227,7 +227,7 @@ func Stats(ctx context.Context, client *containerd.Client, containerIds []string }, } - if err := walker.WalkAll(ctx, containerIds, false); err != nil { + if err := walker.WalkAll(ctx, containerIDs, false); err != nil { return err } diff --git a/pkg/cmd/container/stop.go b/pkg/cmd/container/stop.go index 25b78a9d769..a0fadfd4bb6 100644 --- a/pkg/cmd/container/stop.go +++ b/pkg/cmd/container/stop.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/containerutil" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 9a4f927e2f0..af04bb2c935 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -32,12 +32,12 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" "github.com/containerd/containerd/pkg/progress" - "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/platforms" v1 "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/cmd/image/load.go b/pkg/cmd/image/load.go index b3871279dd5..4741a66b24f 100644 --- a/pkg/cmd/image/load.go +++ b/pkg/cmd/image/load.go @@ -27,10 +27,10 @@ import ( "github.com/containerd/containerd/archive/compression" "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/archive" - "github.com/containerd/containerd/platforms" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/platformutil" + "github.com/containerd/platforms" ) type readCounter struct { diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index abcee6bd86a..e5578569091 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -22,10 +22,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/platforms" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/platforms" "github.com/opencontainers/go-digest" ) diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 64c3b6cc7c8..a5b92b7f9ef 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -28,7 +28,6 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/reference" - refdocker "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" dockerconfig "github.com/containerd/containerd/remotes/docker/config" @@ -45,6 +44,7 @@ import ( "github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/estargz/zstdchunked" estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" + refdocker "github.com/distribution/reference" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 0e0c20d8a60..9dcf5e9cf41 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -24,11 +24,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/platforms" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/containerutil" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" + "github.com/containerd/platforms" ) // Remove removes a list of `images`. diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index 8349fc6c769..09992bc2ba7 100644 --- a/pkg/cmd/image/tag.go +++ b/pkg/cmd/image/tag.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/referenceutil" diff --git a/pkg/cmd/namespace/remove.go b/pkg/cmd/namespace/remove.go index 25a8720cf84..098c097d9ba 100644 --- a/pkg/cmd/namespace/remove.go +++ b/pkg/cmd/namespace/remove.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" ) diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index 8a032433478..566125d23e4 100644 --- a/pkg/cmd/network/create.go +++ b/pkg/cmd/network/create.go @@ -20,7 +20,7 @@ import ( "fmt" "io" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/netutil" ) diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index b18955611e1..eaaf06ad6ba 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "fmt" + "strings" "text/template" "time" @@ -37,11 +38,111 @@ import ( // EventOut contains information about an event. type EventOut struct { Timestamp time.Time + ID string Namespace string Topic string + Status Status Event string } +type Status string + +const ( + START Status = "start" + UNKNOWN Status = "unknown" +) + +var statuses = [...]Status{START, UNKNOWN} + +func isStatus(status string) bool { + status = strings.ToLower(status) + + for _, supportedStatus := range statuses { + if string(supportedStatus) == status { + return true + } + } + + return false +} + +func TopicToStatus(topic string) Status { + if strings.Contains(strings.ToLower(topic), string(START)) { + return START + } + + return UNKNOWN +} + +// EventFilter for filtering events +type EventFilter func(*EventOut) bool + +// generateEventFilter is similar to Podman implementation: +// https://github.com/containers/podman/blob/189d862d54b3824c74bf7474ddfed6de69ec5a09/libpod/events/filters.go#L11 +func generateEventFilter(filter, filterValue string) (func(e *EventOut) bool, error) { + switch strings.ToUpper(filter) { + case "EVENT", "STATUS": + return func(e *EventOut) bool { + if !isStatus(string(e.Status)) { + return false + } + + return strings.EqualFold(string(e.Status), filterValue) + }, nil + } + + return nil, fmt.Errorf("%s is an invalid or unsupported filter", filter) +} + +// parseFilter is similar to Podman implementation: +// https://github.com/containers/podman/blob/189d862d54b3824c74bf7474ddfed6de69ec5a09/libpod/events/filters.go#L96 +func parseFilter(filter string) (string, string, error) { + filterSplit := strings.SplitN(filter, "=", 2) + if len(filterSplit) != 2 { + return "", "", fmt.Errorf("%s is an invalid filter", filter) + } + return filterSplit[0], filterSplit[1], nil +} + +// applyFilters is similar to Podman implementation: +// https://github.com/containers/podman/blob/189d862d54b3824c74bf7474ddfed6de69ec5a09/libpod/events/filters.go#L106 +func applyFilters(event *EventOut, filterMap map[string][]EventFilter) bool { + for _, filters := range filterMap { + match := false + for _, filter := range filters { + if filter(event) { + match = true + break + } + } + if !match { + return false + } + } + return true +} + +// generateEventFilters is similar to Podman implementation: +// https://github.com/containers/podman/blob/189d862d54b3824c74bf7474ddfed6de69ec5a09/libpod/events/filters.go#L11 +func generateEventFilters(filters []string) (map[string][]EventFilter, error) { + filterMap := make(map[string][]EventFilter) + for _, filter := range filters { + key, val, err := parseFilter(filter) + if err != nil { + return nil, err + } + filterFunc, err := generateEventFilter(key, val) + if err != nil { + return nil, err + } + filterSlice := filterMap[key] + filterSlice = append(filterSlice, filterFunc) + filterMap[key] = filterSlice + } + + return filterMap, nil +} + // Events is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/events/events.go func Events(ctx context.Context, client *containerd.Client, options types.SystemEventsOptions) error { eventsClient := client.EventService() @@ -59,6 +160,10 @@ func Events(ctx context.Context, client *containerd.Client, options types.System return err } } + filterMap, err := generateEventFilters(options.Filters) + if err != nil { + return err + } for { var e *events.Envelope select { @@ -68,6 +173,7 @@ func Events(ctx context.Context, client *containerd.Client, options types.System } if e != nil { var out []byte + var id string if e.Event != nil { v, err := typeurl.UnmarshalAny(e.Event) if err != nil { @@ -80,26 +186,41 @@ func Events(ctx context.Context, client *containerd.Client, options types.System continue } } - if tmpl != nil { - out := EventOut{e.Timestamp, e.Namespace, e.Topic, string(out)} - var b bytes.Buffer - if err := tmpl.Execute(&b, out); err != nil { - return err - } - if _, err := fmt.Fprintln(options.Stdout, b.String()+"\n"); err != nil { - return err - } + var data map[string]interface{} + err := json.Unmarshal(out, &data) + if err != nil { + log.G(ctx).WithError(err).Warn("cannot marshal Any into JSON") } else { - if _, err := fmt.Fprintln( - options.Stdout, - e.Timestamp, - e.Namespace, - e.Topic, - string(out), - ); err != nil { - return err + _, ok := data["container_id"] + if ok { + id = data["container_id"].(string) } } + + eOut := EventOut{e.Timestamp, id, e.Namespace, e.Topic, TopicToStatus(e.Topic), string(out)} + match := applyFilters(&eOut, filterMap) + if match { + if tmpl != nil { + var b bytes.Buffer + if err := tmpl.Execute(&b, eOut); err != nil { + return err + } + if _, err := fmt.Fprintln(options.Stdout, b.String()+"\n"); err != nil { + return err + } + } else { + if _, err := fmt.Fprintln( + options.Stdout, + e.Timestamp, + e.Namespace, + e.Topic, + string(out), + ); err != nil { + return err + } + } + } + } } } diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 5c065d7f5ef..d88ec688b3c 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -45,6 +45,7 @@ type RunOptions struct { Detach bool NoDeps bool Tty bool + SigProxy bool Interactive bool Rm bool User string @@ -126,7 +127,7 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { if ro.User != "" { targetSvc.User = ro.User } - if ro.Volume != nil && len(ro.Volume) > 0 { + if len(ro.Volume) > 0 { for _, v := range ro.Volume { vc, err := loader.ParseVolume(v) if err != nil { @@ -135,15 +136,15 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { targetSvc.Volumes = append(targetSvc.Volumes, vc) } } - if ro.Entrypoint != nil && len(ro.Entrypoint) > 0 { + if len(ro.Entrypoint) > 0 { targetSvc.Entrypoint = make([]string, len(ro.Entrypoint)) copy(targetSvc.Entrypoint, ro.Entrypoint) } - if ro.Env != nil && len(ro.Env) > 0 { + if len(ro.Env) > 0 { envs := types.NewMappingWithEquals(ro.Env) targetSvc.Environment.OverrideBy(envs) } - if ro.Label != nil && len(ro.Label) > 0 { + if len(ro.Label) > 0 { label := types.NewMappingWithEquals(ro.Label) for k, v := range label { if v != nil { @@ -160,7 +161,7 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { for k := range svcs { svcs[k].Ports = []types.ServicePortConfig{} } - if ro.Publish != nil && len(ro.Publish) > 0 { + if len(ro.Publish) > 0 { for _, p := range ro.Publish { pc, err := types.ParsePortConfig(p) if err != nil { diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index 6859af2e95e..3e354fe0add 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -23,8 +23,8 @@ import ( "strings" "github.com/compose-spec/compose-go/types" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/reflectutil" diff --git a/pkg/containerinspector/containerinspector.go b/pkg/containerinspector/containerinspector.go index 4ff3624c4c1..97e7c447b4c 100644 --- a/pkg/containerinspector/containerinspector.go +++ b/pkg/containerinspector/containerinspector.go @@ -20,7 +20,7 @@ import ( "context" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/typeurl/v2" diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 67a49f2dd88..b86870a4eee 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -195,7 +195,7 @@ func (m *containerNetworkManager) VerifyNetworkOptions(_ context.Context) error return errors.New("container networking mode is currently only supported on Linux") } - if m.netOpts.NetworkSlice != nil && len(m.netOpts.NetworkSlice) > 1 { + if len(m.netOpts.NetworkSlice) > 1 { return errors.New("conflicting options: only one network specification is allowed when using '--network=container:'") } diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 23d03545177..c00a05abd79 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -266,7 +266,13 @@ func Start(ctx context.Context, container containerd.Container, flagA bool, clie } } detachC := make(chan struct{}) - task, err := taskutil.NewTask(ctx, client, container, flagA, false, flagT, true, con, logURI, detachKeys, namespace, detachC) + attachStreamOpt := []string{} + if flagA { + // In start, flagA attaches only STDOUT/STDERR + // source: https://github.com/containerd/nerdctl/blob/main/docs/command-reference.md#whale-nerdctl-start + attachStreamOpt = []string{"STDOUT", "STDERR"} + } + task, err := taskutil.NewTask(ctx, client, container, attachStreamOpt, false, flagT, true, con, logURI, detachKeys, namespace, detachC) if err != nil { return err } diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index 21fb413701b..e028765d593 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -29,8 +29,8 @@ import ( "strings" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/mount" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/tarutil" diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 40a7726e66d..521059abced 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -24,7 +24,7 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/lockutil" types100 "github.com/containernetworking/cni/pkg/types/100" ) diff --git a/pkg/dnsutil/hostsstore/updater.go b/pkg/dnsutil/hostsstore/updater.go index 58116e8b5b8..b1eb0a890f7 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -24,7 +24,7 @@ import ( "path/filepath" "strings" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/netutil" ) diff --git a/pkg/formatter/formatter.go b/pkg/formatter/formatter.go index f8374ff94e8..eb6c6ddabe5 100644 --- a/pkg/formatter/formatter.go +++ b/pkg/formatter/formatter.go @@ -29,9 +29,9 @@ import ( "golang.org/x/text/language" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/runtime/restart" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/portutil" "github.com/docker/go-units" diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 81bd0d6a425..1193748ee70 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -31,15 +31,15 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/content" "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/rootfs" "github.com/containerd/containerd/snapshots" + "github.com/containerd/errdefs" "github.com/containerd/log" imgutil "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/platforms" "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/specs-go" diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go index 859f1d3cc0c..ff7906cf9b6 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -22,10 +22,10 @@ import ( "io" "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/images/converter/uncompress" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/klauspost/compress/zstd" diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 898b6f1c1e2..a08174ed5d1 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -25,9 +25,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" - dockerreference "github.com/containerd/containerd/reference/docker" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/referenceutil" + dockerreference "github.com/distribution/reference" ) // Filter types supported to filter images. diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 9dd63502cff..df66191e5b5 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -26,8 +26,6 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/platforms" - refdocker "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/snapshots" "github.com/containerd/imgcrypt" @@ -37,6 +35,8 @@ import ( "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/pkg/imgutil/pull" + "github.com/containerd/platforms" + refdocker "github.com/distribution/reference" "github.com/docker/docker/errdefs" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/pkg/imgutil/jobs/jobs.go b/pkg/imgutil/jobs/jobs.go index d03143d956e..57329468065 100644 --- a/pkg/imgutil/jobs/jobs.go +++ b/pkg/imgutil/jobs/jobs.go @@ -25,9 +25,9 @@ import ( "time" "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/remotes" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/pkg/imgutil/push/push.go b/pkg/imgutil/push/push.go index 09930a3fa86..3fd36a3887b 100644 --- a/pkg/imgutil/push/push.go +++ b/pkg/imgutil/push/push.go @@ -28,11 +28,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" "github.com/containerd/containerd/pkg/progress" - "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/imgutil/jobs" + "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sync/errgroup" diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index 2312274f9af..359e2f90d1b 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -173,7 +173,7 @@ type ContainerState struct { } type NetworkSettings struct { - Ports *nat.PortMap `json:",omitempty"` + Ports *nat.PortMap DefaultNetworkSettings Networks map[string]*NetworkEndpointSettings } @@ -337,12 +337,15 @@ func statusFromNative(x containerd.Status, labels map[string]string) string { } func networkSettingsFromNative(n *native.NetNS, sp *specs.Spec) (*NetworkSettings, error) { - if n == nil { - return nil, nil - } res := &NetworkSettings{ Networks: make(map[string]*NetworkEndpointSettings), } + resPortMap := make(nat.PortMap) + res.Ports = &resPortMap + if n == nil { + return res, nil + } + var primary *NetworkEndpointSettings for _, x := range n.Interfaces { if x.Interface.Flags&net.FlagLoopback != 0 { @@ -386,8 +389,11 @@ func networkSettingsFromNative(n *native.NetNS, sp *specs.Spec) (*NetworkSetting if err != nil { return nil, err } - res.Ports = nports + for portLabel, portBindings := range *nports { + resPortMap[portLabel] = portBindings + } } + if x.Index == n.PrimaryInterface { primary = nes } diff --git a/pkg/inspecttypes/dockercompat/dockercompat_test.go b/pkg/inspecttypes/dockercompat/dockercompat_test.go new file mode 100644 index 00000000000..0a89aa7898a --- /dev/null +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -0,0 +1,325 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package dockercompat + +import ( + "net" + "os" + "path/filepath" + "runtime" + "testing" + + "github.com/docker/go-connections/nat" + "github.com/opencontainers/runtime-spec/specs-go" + "gotest.tools/v3/assert" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/containers" + + "github.com/containerd/nerdctl/pkg/inspecttypes/native" +) + +func TestContainerFromNative(t *testing.T) { + tempStateDir, err := os.MkdirTemp(t.TempDir(), "rw") + if err != nil { + t.Fatal(err) + } + os.WriteFile(filepath.Join(tempStateDir, "resolv.conf"), []byte(""), 0644) + defer os.RemoveAll(tempStateDir) + + testcase := []struct { + name string + n *native.Container + expected *Container + }{ + // nerdctl container, mount /mnt/foo:/mnt/foo:rw,rslave; ResolvConfPath; hostname + { + name: "container from nerdctl", + n: &native.Container{ + Container: containers.Container{ + Labels: map[string]string{ + "nerdctl/mounts": "[{\"Type\":\"bind\",\"Source\":\"/mnt/foo\",\"Destination\":\"/mnt/foo\",\"Mode\":\"rshared,rw\",\"RW\":true,\"Propagation\":\"rshared\"}]", + "nerdctl/state-dir": tempStateDir, + "nerdctl/hostname": "host1", + }, + }, + Spec: &specs.Spec{}, + Process: &native.Process{ + Pid: 10000, + Status: containerd.Status{ + Status: "running", + }, + }, + }, + expected: &Container{ + Created: "0001-01-01T00:00:00Z", + Platform: runtime.GOOS, + ResolvConfPath: tempStateDir + "/resolv.conf", + State: &ContainerState{ + Status: "running", + Running: true, + Pid: 10000, + FinishedAt: "0001-01-01T00:00:00Z", + }, + Mounts: []MountPoint{ + { + Type: "bind", + Source: "/mnt/foo", + Destination: "/mnt/foo", + Mode: "rshared,rw", + RW: true, + Propagation: "rshared", + }, + }, + Config: &Config{ + Labels: map[string]string{ + "nerdctl/mounts": "[{\"Type\":\"bind\",\"Source\":\"/mnt/foo\",\"Destination\":\"/mnt/foo\",\"Mode\":\"rshared,rw\",\"RW\":true,\"Propagation\":\"rshared\"}]", + "nerdctl/state-dir": tempStateDir, + "nerdctl/hostname": "host1", + }, + Hostname: "host1", + }, + NetworkSettings: &NetworkSettings{ + Ports: &nat.PortMap{}, + Networks: map[string]*NetworkEndpointSettings{}, + }, + }, + }, + // cri container, mount /mnt/foo:/mnt/foo:rw,rslave; mount resolv.conf and hostname; internal sysfs mount + { + name: "container from cri", + n: &native.Container{ + Container: containers.Container{}, + Spec: &specs.Spec{ + Mounts: []specs.Mount{ + { + Destination: "/etc/resolv.conf", + Type: "bind", + Source: "/mock-sandbox-dir/resolv.conf", + Options: []string{"rbind", "rprivate", "rw"}, + }, + { + Destination: "/etc/hostname", + Type: "bind", + Source: "/mock-sandbox-dir/hostname", + Options: []string{"rbind", "rprivate", "rw"}, + }, + { + Destination: "/mnt/foo", + Type: "bind", + Source: "/mnt/foo", + Options: []string{"rbind", "rslave", "rw"}, + }, + { + Destination: "/sys", + Type: "sysfs", + Source: "sysfs", + Options: []string{"nosuid", "noexec", "nodev", "ro"}, + }, + }, + }, + Process: &native.Process{ + Pid: 10000, + Status: containerd.Status{ + Status: "running", + }, + }, + }, + expected: &Container{ + Created: "0001-01-01T00:00:00Z", + Platform: runtime.GOOS, + ResolvConfPath: "", + HostnamePath: "", + State: &ContainerState{ + Status: "running", + Running: true, + Pid: 10000, + FinishedAt: "0001-01-01T00:00:00Z", + }, + Config: &Config{}, + NetworkSettings: &NetworkSettings{ + Ports: &nat.PortMap{}, + Networks: map[string]*NetworkEndpointSettings{}, + }, + }, + }, + // ctr container, mount /mnt/foo:/mnt/foo:rw,rslave; internal sysfs mount; hostname + { + name: "container from ctr", + n: &native.Container{ + Container: containers.Container{}, + Spec: &specs.Spec{ + Hostname: "", + Mounts: []specs.Mount{ + { + Destination: "/mnt/foo", + Type: "bind", + Source: "/mnt/foo", + Options: []string{"rbind", "rslave", "rw"}, + }, + { + Destination: "/sys", + Type: "sysfs", + Source: "sysfs", + Options: []string{"nosuid", "noexec", "nodev", "ro"}, + }, + }, + }, + Process: &native.Process{ + Pid: 10000, + Status: containerd.Status{ + Status: "running", + }, + }, + }, + expected: &Container{ + Created: "0001-01-01T00:00:00Z", + Platform: runtime.GOOS, + State: &ContainerState{ + Status: "running", + Running: true, + Pid: 10000, + FinishedAt: "0001-01-01T00:00:00Z", + }, + Config: &Config{ + Hostname: "", + }, + NetworkSettings: &NetworkSettings{ + Ports: &nat.PortMap{}, + Networks: map[string]*NetworkEndpointSettings{}, + }, + }, + }, + } + + for _, tc := range testcase { + t.Run(tc.name, func(tt *testing.T) { + d, _ := ContainerFromNative(tc.n) + assert.DeepEqual(tt, d, tc.expected) + }) + } +} + +func TestNetworkSettingsFromNative(t *testing.T) { + tempStateDir, err := os.MkdirTemp(t.TempDir(), "rw") + if err != nil { + t.Fatal(err) + } + os.WriteFile(filepath.Join(tempStateDir, "resolv.conf"), []byte(""), 0644) + defer os.RemoveAll(tempStateDir) + + testcase := []struct { + name string + n *native.NetNS + s *specs.Spec + expected *NetworkSettings + }{ + // Given null native.NetNS, Return initialized NetworkSettings + // UseCase: Inspect a Stopped Container + { + name: "Given Null NetNS, Return initialized NetworkSettings", + n: nil, + s: &specs.Spec{}, + expected: &NetworkSettings{ + Ports: &nat.PortMap{}, + Networks: map[string]*NetworkEndpointSettings{}, + }, + }, + // Given native.NetNS with single Interface with Port Annotations, Return populated NetworkSettings + // UseCase: Inspect a Running Container with published ports + { + name: "Given NetNS with single Interface with Port Annotation, Return populated NetworkSettings", + n: &native.NetNS{ + Interfaces: []native.NetInterface{ + { + Interface: net.Interface{ + Index: 1, + MTU: 1500, + Name: "eth0.100", + Flags: net.FlagUp, + }, + HardwareAddr: "xx:xx:xx:xx:xx:xx", + Flags: []string{}, + Addrs: []string{"10.0.4.30/24"}, + }, + }, + }, + s: &specs.Spec{ + Annotations: map[string]string{ + "nerdctl/ports": "[{\"HostPort\":8075,\"ContainerPort\":77,\"Protocol\":\"tcp\",\"HostIP\":\"127.0.0.1\"}]", + }, + }, + expected: &NetworkSettings{ + Ports: &nat.PortMap{ + nat.Port("77/tcp"): []nat.PortBinding{ + { + HostIP: "127.0.0.1", + HostPort: "8075", + }, + }, + }, + Networks: map[string]*NetworkEndpointSettings{ + "unknown-eth0.100": { + IPAddress: "10.0.4.30", + IPPrefixLen: 24, + MacAddress: "xx:xx:xx:xx:xx:xx", + }, + }, + }, + }, + // Given native.NetNS with single Interface without Port Annotations, Return valid NetworkSettings w/ empty Ports + // UseCase: Inspect a Running Container without published ports + { + name: "Given NetNS with single Interface without Port Annotations, Return valid NetworkSettings w/ empty Ports", + n: &native.NetNS{ + Interfaces: []native.NetInterface{ + { + Interface: net.Interface{ + Index: 1, + MTU: 1500, + Name: "eth0.100", + Flags: net.FlagUp, + }, + HardwareAddr: "xx:xx:xx:xx:xx:xx", + Flags: []string{}, + Addrs: []string{"10.0.4.30/24"}, + }, + }, + }, + s: &specs.Spec{ + Annotations: map[string]string{}, + }, + expected: &NetworkSettings{ + Ports: &nat.PortMap{}, + Networks: map[string]*NetworkEndpointSettings{ + "unknown-eth0.100": { + IPAddress: "10.0.4.30", + IPPrefixLen: 24, + MacAddress: "xx:xx:xx:xx:xx:xx", + }, + }, + }, + }, + } + + for _, tc := range testcase { + t.Run(tc.name, func(tt *testing.T) { + d, _ := networkSettingsFromNative(tc.n, tc.s) + assert.DeepEqual(tt, d, tc.expected) + }) + } +} diff --git a/pkg/logging/cri_logger_test.go b/pkg/logging/cri_logger_test.go index 3788a3c706b..cd7d009bbd8 100644 --- a/pkg/logging/cri_logger_test.go +++ b/pkg/logging/cri_logger_test.go @@ -89,7 +89,7 @@ func TestReadLogs(t *testing.T) { err = ReadLogs(&tc.logViewOptions, stdoutBuf, stderrBuf, stopChan) if err != nil { - t.Fatalf(err.Error()) + t.Fatal(err.Error()) } if stderrBuf.Len() > 0 { t.Fatalf("Stderr: %v", stderrBuf.String()) diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 9339868f2a7..c89dbd6085c 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -28,8 +28,8 @@ import ( "sort" "sync" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/muesli/cancelreader" ) diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index bb938d073a8..2f4a5a9ee44 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -24,14 +24,14 @@ import ( "runtime" "strings" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/userns" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/idgen" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/pkg/strutil" + "github.com/moby/sys/userns" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/mountutil/mountutil_freebsd.go b/pkg/mountutil/mountutil_freebsd.go index 637bdfebc2b..67814348405 100644 --- a/pkg/mountutil/mountutil_freebsd.go +++ b/pkg/mountutil/mountutil_freebsd.go @@ -20,8 +20,8 @@ import ( "fmt" "strings" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" ) diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index 35faafb72ee..1a9bedf9639 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -31,8 +31,8 @@ import ( "regexp" "strings" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" ) diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index f645a167e71..b171d791dac 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -22,8 +22,8 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/nerdctl/pkg/lockutil" "github.com/containerd/nerdctl/pkg/strutil" diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index f6e0079cd9f..839395a9b23 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -31,8 +31,8 @@ import ( "strings" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/lockutil" diff --git a/pkg/platformutil/binfmt.go b/pkg/platformutil/binfmt.go index 11c05b94cf4..bfe1023dc57 100644 --- a/pkg/platformutil/binfmt.go +++ b/pkg/platformutil/binfmt.go @@ -21,7 +21,7 @@ import ( "os" "runtime" - "github.com/containerd/containerd/platforms" + "github.com/containerd/platforms" ) func qemuArchFromOCIArch(ociArch string) (string, error) { diff --git a/pkg/platformutil/layers.go b/pkg/platformutil/layers.go index 1aa18d1504c..8f8aee20dee 100644 --- a/pkg/platformutil/layers.go +++ b/pkg/platformutil/layers.go @@ -21,7 +21,7 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/platforms" + "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/platformutil/platformutil.go b/pkg/platformutil/platformutil.go index 13e90dcdc15..20fa35762b0 100644 --- a/pkg/platformutil/platformutil.go +++ b/pkg/platformutil/platformutil.go @@ -19,8 +19,8 @@ package platformutil import ( "fmt" - "github.com/containerd/containerd/platforms" "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/referenceutil/referenceutil.go b/pkg/referenceutil/referenceutil.go index 86de6558feb..cd824ebeb13 100644 --- a/pkg/referenceutil/referenceutil.go +++ b/pkg/referenceutil/referenceutil.go @@ -21,7 +21,7 @@ import ( "path" "strings" - refdocker "github.com/containerd/containerd/reference/docker" + refdocker "github.com/distribution/reference" "github.com/ipfs/go-cid" ) diff --git a/pkg/rootlessutil/child_linux.go b/pkg/rootlessutil/child_linux.go index 1f6d82bc049..d318463846a 100644 --- a/pkg/rootlessutil/child_linux.go +++ b/pkg/rootlessutil/child_linux.go @@ -19,7 +19,7 @@ package rootlessutil import ( "os" - "github.com/containerd/containerd/pkg/userns" + "github.com/moby/sys/userns" ) func IsRootlessChild() bool { diff --git a/pkg/rootlessutil/port_linux.go b/pkg/rootlessutil/port_linux.go index 108ef6b4602..f0783dc8d65 100644 --- a/pkg/rootlessutil/port_linux.go +++ b/pkg/rootlessutil/port_linux.go @@ -20,7 +20,7 @@ import ( "context" "net" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/rootless-containers/rootlesskit/pkg/api/client" "github.com/rootless-containers/rootlesskit/pkg/port" diff --git a/pkg/signalutil/signals.go b/pkg/signalutil/signals.go index f3f627ed315..ac4baa9662b 100644 --- a/pkg/signalutil/signals.go +++ b/pkg/signalutil/signals.go @@ -23,7 +23,7 @@ import ( "syscall" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" ) diff --git a/pkg/strutil/strutil.go b/pkg/strutil/strutil.go index 233853a8068..f478bffa9b2 100644 --- a/pkg/strutil/strutil.go +++ b/pkg/strutil/strutil.go @@ -36,7 +36,7 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" ) // ConvertKVStringsToMap is from https://github.com/moby/moby/blob/v20.10.0-rc2/runconfig/opts/parse.go diff --git a/pkg/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index 022da8c7df2..e5ea1c58c06 100644 --- a/pkg/taskutil/taskutil.go +++ b/pkg/taskutil/taskutil.go @@ -23,6 +23,8 @@ import ( "net/url" "os" "runtime" + "slices" + "strings" "sync" "syscall" @@ -39,7 +41,8 @@ import ( // NewTask is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/tasks/tasks_unix.go#L70-L108 func NewTask(ctx context.Context, client *containerd.Client, container containerd.Container, - flagA, flagI, flagT, flagD bool, con console.Console, logURI, detachKeys, namespace string, detachC chan<- struct{}) (containerd.Task, error) { + attachStreamOpt []string, flagI, flagT, flagD bool, con console.Console, logURI, detachKeys, namespace string, detachC chan<- struct{}) (containerd.Task, error) { + var t containerd.Task closer := func() { if detachC != nil { @@ -59,7 +62,7 @@ func NewTask(ctx context.Context, client *containerd.Client, container container io.Cancel() } var ioCreator cio.Creator - if flagA { + if len(attachStreamOpt) != 0 { log.G(ctx).Debug("attaching output instead of using the log-uri") if flagT { in, err := consoleutil.NewDetachableStdin(con, detachKeys, closer) @@ -68,7 +71,8 @@ func NewTask(ctx context.Context, client *containerd.Client, container container } ioCreator = cio.NewCreator(cio.WithStreams(in, con, nil), cio.WithTerminal) } else { - ioCreator = cio.NewCreator(cio.WithStdio) + streams := processAttachStreamsOpt(attachStreamOpt) + ioCreator = cio.NewCreator(cio.WithStreams(streams.stdIn, streams.stdOut, streams.stdErr)) } } else if flagT && flagD { @@ -146,6 +150,51 @@ func NewTask(ctx context.Context, client *containerd.Client, container container return t, nil } +// struct used to store streams specified with attachStreamOpt (-a, --attach) +type streams struct { + stdIn *os.File + stdOut *os.File + stdErr *os.File +} + +func nullStream() *os.File { + devNull, err := os.Open(os.DevNull) + if err != nil { + return nil + } + defer devNull.Close() + + return devNull +} + +func processAttachStreamsOpt(streamsArr []string) streams { + stdIn := os.Stdin + stdOut := os.Stdout + stdErr := os.Stderr + + for i, str := range streamsArr { + streamsArr[i] = strings.ToUpper(str) + } + + if !slices.Contains(streamsArr, "STDIN") { + stdIn = nullStream() + } + + if !slices.Contains(streamsArr, "STDOUT") { + stdOut = nullStream() + } + + if !slices.Contains(streamsArr, "STDERR") { + stdErr = nullStream() + } + + return streams{ + stdIn: stdIn, + stdOut: stdOut, + stdErr: stdErr, + } +} + // StdinCloser is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/tasks/exec.go#L181-L194 type StdinCloser struct { mu sync.Mutex diff --git a/pkg/testutil/nettestutil/nettestutil.go b/pkg/testutil/nettestutil/nettestutil.go index 960d7738bca..5feb322df65 100644 --- a/pkg/testutil/nettestutil/nettestutil.go +++ b/pkg/testutil/nettestutil/nettestutil.go @@ -24,7 +24,7 @@ import ( "net/http" "time" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" ) func HTTPGet(urlStr string, attempts int, insecure bool) (*http.Response, error) { diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 340ff7bf059..433f0a319d2 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -31,6 +31,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/containerd/containerd/defaults" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/buildkitutil" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/infoutil" @@ -350,6 +351,11 @@ func (c *Cmd) Run() *icmd.Result { return icmd.RunCmd(c.Cmd) } +func (c *Cmd) Start() *icmd.Result { + c.Base.T.Helper() + return icmd.StartCmd(c.Cmd) +} + func (c *Cmd) CmdOption(cmdOptions ...func(*Cmd)) *Cmd { for _, opt := range cmdOptions { opt(c) @@ -452,7 +458,7 @@ func (c *Cmd) AssertOutStreamsExactly(stdout, stderr string) { msg += fmt.Sprintf("stderr mismatch, expected %q, got %q\n", stderr, serr) } if msg != "" { - return fmt.Errorf(msg) + return fmt.Errorf("%s", msg) } return nil } @@ -532,6 +538,12 @@ func GetEnableIPv6() bool { } func GetDaemonIsKillable() bool { + if flagTestKillDaemon && strings.HasPrefix(infoutil.DistroName(), "Ubuntu 24.04") { // FIXME: check systemd version, not distro + log.L.Warn("FIXME: Ignoring -test.kill-daemon: the flag does not seem to work on Ubuntu 24.04") + // > Failed to kill unit containerd.service: Failed to send signal SIGKILL to auxiliary processes: Invalid argument\n + // https://github.com/containerd/nerdctl/pull/3129#issuecomment-2185780506 + return false + } return flagTestKillDaemon } diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index adbc5fbc775..84316b8535b 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -55,6 +55,25 @@ var ( // It should be "connection refused" as per the TCP RFC. // https://www.rfc-editor.org/rfc/rfc793 ExpectedConnectionRefusedError = "connection refused" + + SigProxyTrueOut = "received SIGINT" + SigProxyTimeoutMsg = "Timed Out; No signal received" + SigProxyTestScript = `#!/bin/sh + set -eu + + sig_msg () { + printf "` + SigProxyTrueOut + `" + end + } + + trap sig_msg INT + timeout=0 + while [ $timeout -ne 10 ]; do + timeout=$((timeout+1)) + sleep 1 + done + printf "` + SigProxyTimeoutMsg + `" + end` ) const (